2017-03-06 12 views
4

私はC#でnunitを使っていくつかの単体テストを書いています。次のコードを考えてみましょう:単体テストをループで実行するのは悪い習慣ですか?

[Test()] 
    public void TestCarCost() { 
     for (int i = 0; i < Examples.exampleCount; i++) { 
      Car car = new Car(Examples[i]); 
      Assert.AreEqual (car.getCost(), Examples[i].cost, "Test " + (i + 1) + " failed"); 
     } 
    } 

のは、例を言ってみましょうあなたは、私が(car.getCostのいずれかのバグをテストしようとしています見ることができるように)、車の種類ごとに異なる可能な入力をテストするためのいくつかの静的データを持つクラスです関数。今ではループ内でこれを行うのはどうにかして間違っていると感じます。たとえば、アサーションのいずれかが失敗した場合、常に同じコード行にあなたを送ります。さらに、[Test()] nunitでアサーションが失敗したときには、すぐにテストコードの残りの部分を終了させることができます。つまり、ループ内にすべてがあり、nr 1が失敗すると、他のものが失敗したかどうかを確認することはできません。明示的にすべてのテストを書くことは本質的にはコピーされたコードを書いているので、正しく感じられません。この状況では、何が良い習慣と考えられるでしょうか?単体テストでも同様のコードが大量にあるのは大丈夫ですか?私が紛失している優雅な解決策はありますか?

+2

NUnitの 'TestCase'属性はここで使用できます。ここでは「例」とは何ですか? –

答えて

5

TestCaseAttribute代わりにループを使用することをお勧めします。詳しくはlinkをご覧ください。あなたのケースでは

は次のようになります。

[TestCase(1)] 
[TestCase(2)] 
[TestCase(3)] 
public void TestCarCost (int id) 
{   
    Car car = new Car(Examples[id]); 
    Assert.AreEqual (car.getCost(), Examples[id].cost, "Test " + (i + 1) + " failed"); 

} 

ここでは、単一のテストメソッドに対して複数のテストケースを作成することができます。各テストケースに対して、TestCase()属性でパラメータを指定し、テストメソッドにidとして渡すことができます。

idに基づいて、あなたのリソースにアクセスすることができます。例題[id]。

私はそれぞれのケースを監視でき、追加のロジックを必要としないので、むしろこの方法で使用します。

また、単体テストにロジックを追加すると、失敗する可能性が増し、そのロジックの精度に依存します。

7

NUnitにはparameterized testsの組み込みサポートがあります。あなたの例の値(実際には、テスト入力)で表示されない場合

[TestCase("Example Value 1", ExpectedResult=123.4)] 
[TestCase("Example Value 2", ExpectedResult=567.8)] 
[TestCase("Example Value 3", ExpectedResult=901.2)] 
public void TestCarCost (string exampleValue) { 
    Car car = new Car(exampleValue); 
    return car.GetCost();   
} 

:あなたの例のデータ(すなわち値がstringのように、属性に表示できる)シンプルであれば、あなたのテストはTestCase attributesを使用して、このようなものを見ることができます属性は、あなたはあなたのための値を提供しますメンバーを示すためにTestCaseSource attributeを使用することができます。

[TestCaseSource(nameof(Examples))] 
public void TestCarCost (ExampleInput exampleValue) { 
    Car car = new Car(exampleValue); 
    return car.GetCost();   
} 

public IEnumerable<ITestCaseData> Examples { 
    get { 
     yield return new TestCaseData(new ExampleInput(1,2)).Returns(123.4); 
     yield return new TestCaseData(new ExampleInput(3,4)).Returns(567.8); 
     yield return new TestCaseData(new ExampleInput(5,6)).Returns(901.2); 
    } 
} 
+0

私は他の投稿を受け入れましたが、あなたの答えは非常に洞察力もあります、ありがとう。それは確かに私にとっては将来的には有益なことでしょう。 – TheMountainThatCodes

関連する問題