この場合、テストごとに1つのアサートに固執していますか?


10

テストしているクラスがあります。クラスには関数があります:apply(List<IRule> rules, List<ITarget> targets);

1つのテストで、各ターゲットが1つのルールaに渡されていることを確認します。

rule1.AssertWasCalled(fnord => fnord.Test(target1));
rule1.AssertWasCalled(fnord => fnord.Test(target2));
rule1.AssertWasCalled(fnord => fnord.Test(target3));

自分を単一の表明文に限定することはかなりホブゴブリンだと私には思えます。この仮定は正しいですか、それとも各ターゲットが実際にテストされたと断言できる他の方法がありますか?


私はfnordsを見ることができます!
ロスパターソン、

回答:


15

3つのアサートは本質的に1つのテストです。コレクションのメソッドの動作をテストして、各項目が特定の呼び出しのパラメーターになっている(つまり、各項目が適切に処理されている)ことを確認します。

データを3回、3つの異なる方法で設定することは、いくつかのアサートを使用する代わりの方法よりも無駄であり、読みにくくなります。

単一のアサート「ルール」は、同じメソッドで異なるタイプのアサートを作成すること(本質的に異なるものをテストすること)に関するものであり、単一の動作をテストするこの場合には実際には適用されません。


3
実際、ルールはユニットテストごとに複数の論理アサートです。それらを1つの上位レベルにグループ化して、さまざまなテストで再利用できると断言できます。
Laurent Bourgault-Roy

5

これは、テストを1つの問題に集中させるために、テストルールごとにこの1つが存在すると信じています。1つのテストで20の項目をテストする場合、カバレッジが何であるかを知るのは非常に困難です。単語その中でテストメソッドに名前を付けることができない場合、問題が発生していることがわかります。たとえば、テストメソッドの名前がより正確なtestFooIsTrueAndDbExistsAndBarIsNullAndAnExceptionDoesntOccur()場合は、1つのテストでテストしすぎている可能性があります。

あなたの場合、おそらく3回アサートしても問題ないと思います。コードを読みやすくするには、これらの3つのアサートをと名付けられたメソッドに抽出できますassertWasCalledOnTargets(...)


3

あなたの特定の例では、あなたが次のようなことをするなら、あなたは「1つの」assertステートメントで逃れることができます:

foreach target in targets
{
     rule1.AssertWasCalled(fnord => fnord.Test(target))
}

これは、1つのテストで複数のアサートがあることに罪悪感を感じないようにするためです。


私は以前にこれをやったことがあります。行くのに悪い方法ではありません。読みやすく、その内容を理解できます。
CokoBWare

1

私もこれで苦労しました。

純粋主義者(私の中で)は、テストごとに1つのアサートを要求するので、問題がどこで発生したかを* 正確に * 知ることができます。

そして、同じ、冗長なテストセットアップコードの多くをカットアンドペーストすることに気づきました。これの3番目または4番目のレイヤーの後、「Oy!Enough!」と言い始めます。

私の妥協点は、「決して」壊れない側面を見つけることでした。そして、それらの断片を重ねて、壊れる可能性のある新しい要素を1つ追加します。明確にするために、1つのテストで複数の揮発性領域を重ねることは、この妥協の違反になります。


1
あなたはチェックアウトする必要がありAssumeます。今日それについて学んだ。
ウェインヴェルナー、

1

のセットアップコードがのセットアップコードtarget1と異なる場合target2、このタイプのコーナーカットにより、最終的にテスト初期化コードが非常に長くなる傾向があります。これは今度は混乱するか、リファクタリングされて再利用されることになります。テストがリファクタリングを正当化するほど複雑な場合、テストはおそらく複数のことをテストしています。

各ターゲットのセットアップコードが基本的に同じである場合、テストを複数の個別のテストに分割することはおそらくやりすぎです。

場合target1target2同じインタフェースの異なった実装である、あなたの代わりに、インターフェイスにユニットテストを追加(そして、あなたのテストフレームワークは、そのインターフェイスのすべての実装のためのテストを生成することができます)する必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.