- PR -

NUnit での Singleton なクラスのテスト方法

1
投稿者投稿内容
kurage
会議室デビュー日: 2006/10/28
投稿数: 12
投稿日時: 2008-05-06 01:39
kurage と申します。.NET 2005 を使用しています。

NUnitを使用して、Singleton なクラスのテストを行おうと考えました。

ところが、複数のテストケースをまとめて実行すると、
各テストケースに1つのインスタンスが使用されるため、
テストの内容によっては結果が NG となってしまいます。
(フィールドの値が各テストケースを通じて保持されるため)

私は以下の様な対策案しか思いつく事ができませんでした…。

・テストケースを 1 つ 1 つ実行する。
  …面倒です。
・クラスに、初期化用のメソッドを追加し、
 テストケース毎にそのメソッドを頭部分で実行する。
  …テストのためにクラスにメソッドを追加するのはおかしな話??

このような場合、どういった対策が考えられますでしょうか?
ご教示いただければ幸いです。
よこけん
大ベテラン
会議室デビュー日: 2006/01/31
投稿数: 216
投稿日時: 2008-05-06 11:55
シングルトンは自動テストとの相性が良くありません。シングルトンオブジェクトに依存するクラスをテストする際に、シングルトンオブジェクトを切り離してテストすることが難しくなるなどのデメリットもあります。
僕ならシングルトンを作らないようにします。代わりに DI (依存性の注入) パターンを良く使います。

> テストのためにクラスにメソッドを追加するのはおかしな話??
テストが容易にできる設計は良い設計と言われています。テストのために設計が変わるのも場合によっては有りです。
最初に書いた、「シングルトンを使わない」という解決策もテストのための設計変更です。
今回の場合は、初期化メソッドの追加よりも、シングルトンを使わないという解決策の方が、より優れた設計に繋がると僕は思います。

_________________
C#と諸々
Anthyhime
ぬし
会議室デビュー日: 2002/09/10
投稿数: 437
投稿日時: 2008-05-06 13:43
引用:

・クラスに、初期化用のメソッドを追加し、
 テストケース毎にそのメソッドを頭部分で実行する。
  …テストのためにクラスにメソッドを追加するのはおかしな話??



まったくそんなことはなく、そのためにプリプロセッサがあるのです。
jama
常連さん
会議室デビュー日: 2006/09/12
投稿数: 45
投稿日時: 2008-05-06 17:30
引用:
ところが、複数のテストケースをまとめて実行すると、
各テストケースに1つのインスタンスが使用されるため、
テストの内容によっては結果が NG となってしまいます。
(フィールドの値が各テストケースを通じて保持されるため)


グローバル変数の代用になっていませんか?
GENZO
大ベテラン
会議室デビュー日: 2003/11/26
投稿数: 111
お住まい・勤務地: 名古屋
投稿日時: 2008-05-06 21:33
引用:

kurageさんの書き込み (2008-05-06 01:39) より:
・テストケースを 1 つ 1 つ実行する。
  …面倒です。


リフレクション使ってフィールドを初期化する方法があります。
テストを実行するたびに実施する必要があるので、面倒くささは同じレベルかも知れませんね。

しかし、シングルトンなら、フィールドの値が保持される前提でテストされるのは正しい気がします。
kurage
会議室デビュー日: 2006/10/28
投稿数: 12
投稿日時: 2008-05-06 23:13
皆様、アドバイスを有難うございます。


●よこけん さん

> 僕ならシングルトンを作らないようにします。
> 代わりに DI (依存性の注入) パターンを良く使います。

DI については、以前から興味はあるものの実装を試みたことがないので、
今回を良い機会にして勉強してみます。

> テストが容易にできる設計は良い設計と言われています。
> テストのために設計が変わるのも場合によっては有りです。

なるほど。
あくまでテストは設計に付随して行うものだという考えでいたのですが、
そういう考え方があるのですね。勉強になります。

> 今回の場合は、初期化メソッドの追加よりも、
> シングルトンを使わないという解決策の方が、より優れた設計に繋がると僕は思います。

諸事情ありまして、今回設計を変更することはできないのですが、
個人的には再考してみたいと思います。


●Anthyhime さん

> まったくそんなことはなく、そのためにプリプロセッサがあるのです。

すみません。
プリプロセッサについては、基礎は知っている(つもり)ですが、
今回の問題に関してどのように活用できるのかが思いつきませんでした。
何か、ヒントをいただけませんでしょうか。


●jama さん

> グローバル変数の代用になっていませんか?

これにつきましては、再度確認してみます。


●GENZO さん

> リフレクション使ってフィールドを初期化する方法があります。

実は、NG になってしまうテストの内容は、
フィールドが正しい値で初期化されているかを調べるテストなのです。

テストケースの実行順が、

1) フィールド A を何らかの値で変更する必要があるテスト
2) フィールド A が正しい値で初期化されているかを調べるテスト

という場合、2 のテスト結果が NG になってしまうのです…(当然ですが) 。

テストケースの実行順を 2→1 とすれば OK になるのですが、
NUnit のテストの実行順はメソッドの名前順のようですし、
そもそもテストの実行順で結果が変わるというのは問題ありと思い、困っています。


----
NUnit の環境設定(設定ファイルなど)で、テストケースを実行する単位の設定(※)が
できるなど、何か回避策があればと考えていたのですが、
そんな都合の良いものは無いのでしょうか。
※複数のテストケースをまとめて実行する際、
 内部的にテストケース毎に再起動(?)するような設定とか…。
kurage
会議室デビュー日: 2006/10/28
投稿数: 12
投稿日時: 2008-05-07 00:53
●GENZO さん

上の投稿をした後で気づいたのですが…。

リフレクションを使うというのは、Singleton を実現するための
静的フィールドを、リフレクションを使って
初期化(new)するという意味だったのでしょうか??

もしそうでしたら、勘違いしてしまってすみませんでした(>_<
1

スキルアップ/キャリアアップ(JOB@IT)