2013-03-01 6 views
9

私は、一般的にカスタム電子メールメッセージの作成を制御する単体テストの集合を持つParametrizedテストクラスを持っています。今のクラスは、パラメータ化されたクラスで使用される因子に依存する多くのテストを持っています。テストの流れはすべてのテストで同じです。テストの例:テスト中の文

@Test 
public void testRecipientsCount() { 
    assertEquals(3, recipientsCount); 
} 

は、私は受信者のリストにいくつかの余分な内部の電子メールを追加私の電子メールクラスに余分なfuncionalityを追加する必要がありました、それが唯一の例いくつかのために起こり、それは私の問題につながります。

私は作成されたメッセージの量を表明したいと言います。古いテストの場合は、それぞれのケースで同じでしたが、今の場合によって異なります。

@Test 
public void testRecipientsCount(){ 
    if(something) { 
     assertEquals(3, recipientsCount); 
    } 
    else { 
     assertEquals(4, recipientsCount); 
    } 
} 
... 

が、私より経験豊富な同僚たちはテストクラスでIFSを避ける​​べきであると言う(と私はちょっとそれに同意):私にとって最も直感的な方法は、if文を追加することでした。

私は、2つのテストのclassessで分割テストがうまくいくかもしれないと思っていましたが、それは両方のクラスで冗長なコードにつながります(私はまだ非永遠のメッセージが作成されたかどうかチェックしなければなりません。そのうちの1つに数行追加されました。

私はこれをどうやって行うのですか?冗長コード(パラメータ化されていないクラスを使用しないと、より冗長なコードを生成する場合)を使用しないでください。

+0

は 'いくつかの追加を追加します受信者のリストへの内部電子メール。そのクラスに内部アドレスのリストが注入されていますか?その場合、ほとんどのテストでそのリストを消去し、そのリストに1つまたは2つの 'testInternalMail'テストを入れてください。 –

+0

これは、Parametrizedテストクラスでは可能ではないと思います。引数のセットごとに実行することをお勧めするテストケースを追加しました。アサーションはいくつかの点で異なります。あなたのソリューションは、Parametrizedクラスなしで動作するだろうが、私はちょっとそれを避けたい。 – Raidmaster

+0

あなたの投稿コードをより完全な(しかしまだ小さくて偽物の)テストクラスに変更して、パラメータの設定方法を理解できますか? –

答えて

3

私の意見では、Junitはプロトコルのように読むべきです。 これは、テストケースをより読みやすくするために冗長なコードを書くことができることを意味します。 ビジネスロジックとネガティブケースの可能な各if文のテストケースを記述します。それは100%テストカバレッジを取得する唯一の方法です。 私は構造を使用します。それはあなたのコードの複雑さを軽減し、あなたがが利用できるようにしている

abstract class YourBusinessObjectAssert{ 
    public static void assertYourBussinessObjectIsValid(YourBusinessObject pYourBusinessObject,  Collection<YourBusinessObject> pAllYourBusinessObject) { 
for (YourBusinessObject lYourBusinessObject : pAllYourBusinessObject) { 
    if (lYourBusinessObject.isTechnicalEqual(pYourBusinessObject)) { 
    return; 
    } 
} 
assertFalse("Could not find requested YourBusinessObject in List<YourBusinessObject>!", true); 
} 
} 

- testdata preparation 
- executing logic 
- check results 
- clear data 

さらにあなたは複合体が自身の抽象クラスで、大きなオブジェクトのアサート書くべきを他の開発者。

0

単体テストは、私の意見では、可能であれば1つしか試してはいけません。 if文が必要な場合は、if/elseコードの各ブロックに対して1つ以上の単体テストが必要になるでしょう。

私はテストが物語のように読むべきでしょうね可能であれば - 私の好みのレイアウト(およびそのない私の考え:-) - そのかなり広く使われている)である:

- given: do setup etc 
- when: the place you actually execute/call the thing under test 
- expect: verify the result 

ユニットのもう一つの利点テストのテストは、障害が発生したときにその原因が明確になった場合に発生する可能性があります。長いテストで多くの結果が得られれば、テストが失敗した理由を説明するのがずっと難しくなります。

0

なぜ、各メソッドに共通することをテストするプライベートメソッドはありませんか? (おそらくtestCommonStuff()方法のためのいくつかの入力パラメータを持つ)ような何か:あなたは冗長なコードを取得しないと、あなたは小さなテストにテストを分割することができ

@Test 
public void testRecipientsCountA(){ 
    testCommonStuff(); 
    // Assert stuff for test A 
} 

@Test 
public void testRecipientsCountB(){ 
    testCommonStuff(); 
    // Assert stuff for test B 
} 

private void testCommonStuff() { 
    // Assert common stuff 
} 

この方法です。また、実際に同じものをテストする必要がある場合は、テストのエラーが起こりにくくなります。どのテストが失敗したかはまだ分かりますので、トレーサビリティは問題ありません。

+0

私はParametrizedクラスを使用し、引数のセットごとに両方のテストケースを実行します。正しい方法は、実際の引数に応じて1つだけ実行することです。 – Raidmaster

+0

@ Badman6私は完全にそれを取得していません。 「しかし、それは両方のクラスで冗長なコードにつながるでしょう(私は、非永遠のメッセージが作成されたかどうか、サイズ、内容などを調べなければなりません)。これは、あなたが1つ以上のテストメソッドでコードを再定義したことを意味するものではありませんか?もしそうなら、上記のような独自のメソッドでそれを持つことができ、それを実行すべき各メソッドから呼び出すことができます。 – Magnilex

+0

それはそうではありません。受信者数は、パラメータクラスの引数プロバイダで指定されたパラメータによって異なります。 Parametrizedクラスの冗長コードを2つのクラス(1つは内部受信者がない場合、1つはクラス)に分割した結果になります。テストのためにクラスを共有するコードは本当にオプションではありません。あなたは解決策はありません。Parametrizedクラスのためではありません。 – Raidmaster

0

パラメータ化されたテストで、あなたがしていることをきちんとやり遂げることが可能かどうかはわかりません。一部のフィーチャのパラメータに基づいて異なるテストケースの動作が必要な場合は、パラメータが設定されていない別のテストクラスでこれらのフィーチャを別々にテストする方がよい場合があります。

本当にパラメータ化テストクラスのすべてを維持したいならば、単純な主張として、あなたの例のテストは、少なくとも読み取るように、私は、ヘルパー関数を作るために傾くことになります。

@Test 
public void testRecipientsCount(){ 
    assertEquals(expectedCount(something), recipientsCount) 
} 

private int expectedCount(boolean which) { 
    if (something){ 
     return 3; 
    } 
    else { 
     return 4; 
    } 
} 
関連する問題