web-dev-qa-db-ja.com

コンストラクターの単体テストは重要ですか?

コンストラクターを単体テストする必要はありませんか?このようなコンストラクタがあるとします:

IMapinfoWrapper wrapper;
public SystemInfo(IMapinfoWrapper mapinfoWrapper)
{
    this.wrapper = mapinfoWrapper;
}

このコンストラクターの単体テストを作成する必要がありますか?ラッパー変数のゲッターがないため、テストする必要はありません。

71
Nathan W

単体テストは、オブジェクトの公開状態、動作、および相互作用をテストすることです。

コンストラクタにプライベートフィールドを設定するだけの場合、テストするものは何ですか?

単純なアクセッサとミューテータをユニットテストする必要はありません。それは馬鹿げているだけで、誰にも役に立たない。

93
yfeldblum

はい。コンストラクターにロジックがある場合は、テストする必要があります。プロパティを設定するだけでは、ロジックIMOではありません。条件、制御フローなどISロジック。

編集: IMapinfoWrapperがnullの場合、依存関係が必要な場合はおそらくテストする必要があります。もしそうなら、それは論理であり、ArgumentNullExceptionまたは何かをキャッチするテストが必要です。テストは、コードの動作を定義する仕様です。 ArgumentNullExceptionがスローされる場合は、テストで指定する必要があります。

35
Brian Genisio

Q:コンストラクターでメンバー変数を設定している場合、なぜ設定するのですか?.

A:コンストラクターで設定することによってのみ合格することができる失敗した単体テストがあるためです。

このロジックを使用して、ユニットテストをパスするコードのみを作成する場合(テスト駆動開発)、質問に対する答えはすでに得られています。

13
John Sonmez

いいえ。その機能は、クラスの他のすべての単体テストによってテストされます。

8
Draemon

絶対にコンストラクターをテストする必要があります。デフォルトのコンストラクターがある場合は、呼び出すことができるかテストする必要があります。後でクラスが変更された場合-おそらくシングルトンになりますか、パラメータを必要とするコンストラクタを優先してデフォルトのコンストラクタが削除されますか?その場合、テストは失敗し、その変更を警告する必要があります(そのため、新しい要件を満たすようにクラスまたはテストを修正できます)。

デフォルトコンストラクタの存在は、テストが必要な要件です。すべてのコンストラクターが他の場所でテストされるプライベートメンバーを設定する場合でも、パラメーターなしのコンストラクターがあるという事実をテストする必要があります。

6
c g

コンストラクターにロジックが含まれている場合、コンストラクターをテストしています。プライベート状態の検証または条件設定。検証エラーは、コンストラクターからスローされる例外で終わります。実行が成功すると、コンストラクターで設定された状態に応じて特定の動作を示すオブジェクトが作成されます。いずれにしても、テストが必要です。しかし、コンストラクターテストはすべて同じように見えるため、退屈です-コンストラクターを呼び出し、アサーションを作成します。多くの場合、テストメソッドの宣言は、テストロジック全体よりも多くのスペースを必要とします...そこで、コンストラクターの宣言的テストを記述するのに役立つ簡単なテストライブラリを作成しました:

これは、1つのクラスのコンストラクターで7つのテストケースを試している例です。

[TestMethod]
public void Constructor_FullTest()
{

    IDrawingContext context = new Mock<IDrawingContext>().Object; 

    ConstructorTests<Frame>
        .For(typeof(int), typeof(int), typeof(IDrawingContext))
        .Fail(new object[] { -3, 5, context }, typeof(ArgumentException), "Negative  length")
        .Fail(new object[] { 0, 5, context }, typeof(ArgumentException), "Zero length")
        .Fail(new object[] { 5, -3, context }, typeof(ArgumentException), "Negative width")
        .Fail(new object[] { 5, 0, context }, typeof(ArgumentException), "Zero width")
        .Fail(new object[] { 5, 5, null }, typeof(ArgumentNullException), "Null drawing context")
        .Succeed(new object[] { 1, 1, context }, "Small positive length and width")
        .Succeed(new object[] { 3, 4, context }, "Larger positive length and width")
        .Assert();

}

このようにして、多くを入力することなく、コンストラクタに関連するすべてのケースをテストできます。

4
Zoran Horvat

多くのFDA規制環境では、クラスの構築を含め、より重要なコードを100%テストする必要があります。そのため、コンストラクターのテストは、テストする理由に関係なく、時には必要になります。また、静的分析ツールを使用する企業は、コードがスムーズに実行されエラーが発生しない場合でも、エラーが発生しないように、クラスのすべてのデータメンバーが適切に初期化されていることを確認する必要があります。通常、データメンバーの初期化はコンストラクターで行われます...ただ考えてみてください。

3
Brandon

場合によります。

あなたが与えた例のような単純なもののために、専用のコンストラクターテストを書こうとは思いません。

ただし、パラメーターの検証など、コンストラクターに論理テストがある場合は、絶対に可能です。元のポスターのように、可能であればコンストラクターで作業を行いませんが、パラメーターの検証を行う必要があることはよくあります。この場合、コンストラクタがsomeを実行しないようにすることは避けられません。コンストラクターにロジックがある場合、常に間違っている可能性があります。したがって、他のメソッド呼び出しと同様に処理し、適切にテストします。

3
Mark Simpson

これに対する答えは「はい」だと思います。

恐らく、コンストラクターに明示的な値が割り当てられていない場合、多くの場合、null参照ではなく初期化されたオブジェクトの状態を想定するコードがたくさんあります。

初期化されたパブリックメンバーの値が変更されたときに警告するために、コンストラクターテストを中断させてうれしいです。これは防御テストに関するものです-私は実用的であり、テストを行うよりも喜んでおり、有用または有用ではないことが示されたら削除します。

1
badcop666

100%のカバレッジを信じています。また、物事をモックしたり、物事を設定したり取得したりするだけで単純な相互作用をテストするのではなく、機能をチェックするより多くの統合/受け入れテストによって100%のカバレッジを実現します。したがって、非常に優れた統合/受け入れテストを作成することになった場合は、すべてのコンストラクター(およびセッターやゲッターなどの単純なメソッド)を呼び出す必要があります。

1
digiarnie

開発者が状態ロジックを変更できないことを確認していない限り、アクセサーとミューテーターのテストも必要です。たとえば、Singletonのデザインパターンを使用する場合、多くの場合、アクセサーまたはプロパティが使用され、クラスが初期化されていない場合、コンストラクターはプライベートであるため、アクセサーから実行されます。 C++では、クラスのデータメンバーを変更できない関数をconstまたはstaticにすることができます。 (注:これらの変数はしばしばグローバルであるため、静的を使用することは少し危険です)。時間?メンテナンスは絶対に簡単です。

1
Brandon

SystemInfoのインスタンスの動作は、wrapperの値に依存しますか?

何か問題が発生する可能性がある場合(例:null値が破損を引き起こす場合)、そのような状況を説明するシナリオを作成し、それらを使用して適切な単体テストの定義を推進することをお勧めします。

すべてのシナリオがIMapinfoWrapperのプライベートインスタンスの状態または動作に依存するようになる場合は、代わりにそのクラスで単体テストを作成することをお勧めします。

0
joel.neely

コンストラクターにクラスの初期化などのロジックが含まれている場合は、コンストラクターをテストする必要があると思います。または、コンストラクターに初期化を設定すると、テスト対象のコードのテスト容易性が低下することを開発者と話すことができます。

0
Magus

コンパイラを書いているのでなければ、コンパイラは割り当てを行うためのコードを生成できることをテストするだけなので、これは通常無意味です。

さて、より一般的な状況では、ラッパーで何か他のことをしたい場合は、おそらくポイントがあります。たとえば、nullを渡そうとした場合、ArgumentNullExceptionをスローできます。理論的には、ユニットテストがあります。それでも、テストの価値はごくわずかです。

個人的に、コンストラクターを明示的にテストすることはほとんどありません。それらがテストを必要とするほど複雑な場合、コードが少し臭い側にあると感じる傾向があります。

0
Jim Cooper