2017-02-26 9 views
2

のために複数のデータレコード私は単体テストにかなり新しいですし、次のコードのxUnitとテスト

public class PowerOf 
{ 
    public int CalcPowerOf(int @base, int exponent) { 
     if (@base == 0) { return 0; } 
     if (exponent == 0) { return 1; } 
     return @base * CalcPowerOf(@base, exponent - 1); 
    } 
} 

を持って、私はそれのために書いたユニットテスト(xUnitフレーム付き)が最初にこの1だったが、私は適切なアプローチであるかどうか、または別のパターンを使用する必要があるかどうかは不明です。 私が知りたかったことは、xUnitのドキュメント上にドキュメントやリファレンスの例がないので、これが複数のデータセットを "単体テスト"に渡すための正しい使用法であるかどうかです。

[Fact] 
    public void PowerOfTest() { 
     foreach(var td in PowerOfTestData()) { 
      Assert.Equal(expected, CalcPowerOf(@base, exponent)); 
     } 
    } 

    public class TestData { 
     int Base {get;set;} 
     int Exponent {get;set;} 
     int ExpectedResult {get;set;} 
    } 

    public List<TestData> PowerOfTestData() { 
     yield return new TestData { Base = 0, Exponent = 0, TestData = 0 }; 
     yield return new TestData { Base = 0, Exponent = 1, TestData = 0 }; 
     yield return new TestData { Base = 2, Exponent = 0, TestData = 1 }; 
     yield return new TestData { Base = 2, Exponent = 1, TestData = 2 }; 
     yield return new TestData { Base = 5, Exponent = 2, TestData = 25 }; 
    } 

答えて

4

あなたはxUnitの中で専門的な構築物を使用する方が良いと思いますので、「データ駆動型テスト」と呼ばれるハンドルTheoryと呼ばれます。 testmethodをTheory属性で装飾し、入力パラメーターと期待される結果を持つstatic「メンバー」を、TestDataクラスですでに行ったように戻してください。以下の例を参照し、xUnitのドキュメント"Writing your first theory"を参照してください。

私は以下のようにあなたのコードをリファクタリングします。まず、属性TheoryMemberDataでテストを飾り、TestDataクラスのように、テストに "@base"、 "exponent"、 "expectedResult"というパラメータを追加します。 xUnitはTestDataクラスを使用できないため、IEnumerable<object>しか受け付けず、静的であることが要求されますが、foreachループ構造の利点は、すべてのテストが別々に実行されることです。特定のデータセットを使用して実行するたびにを実行すると、緑色または赤色のフラグが表示されます。

public class PowerOfTests 
{ 
    [Theory] 
    [MemberData(nameof(PowerOfTestData))] 
    public void PowerOfTest(int @base, int exponent, int expected) { 
     Assert.Equal(expected, CalcPowerOf(@base, exponent)); 
    } 

    public static IEnumerable<object[]> PowerOfTestData() { 
     yield return new object[] { 0, 0, 0 }; 
     yield return new object[] { 0, 1, 0 }; 
     yield return new object[] { 2, 0, 1 }; 
     yield return new object[] { 2, 1, 2 }; 
     yield return new object[] { 2, 2, 4 }; 
     yield return new object[] { 5, 2, 25 }; 
     yield return new object[] { 5, 3, 125 }; 
     yield return new object[] { 5, 4, 625 }; 
    } 
} 
+0

特別なクラスを使用することはできませんか? – RecursEve

+0

でも可能ですが、xUnitのドキュメントで言及されているように、常にIEnumerableの 'object []'を返さなければなりません。 –

2

あなたのケースで間違ったデータを定義するために、クラスメンバーを使用しています。この方法は、実行時に値が指定されている(おそらく1〜MAXの値をループしている)場合に使用します(ハードコードされたデータがあります)。私はこのアプローチがより良いと思います:

[Theory] 
[InlineData(0, 0, 0) 
[InlineData(0, 1, 0) 
[InlineData(2, 0, 1) 
[InlineData(2, 1, 2) 
[InlineData(2, 2, 4) 
[InlineData(5, 2, 25) 
[InlineData(5, 3, 125) 
[InlineData(5, 4, 625) 
public void PowerOfTest(int @base, int exponent, int expected) 
{ 
    var result = CalcPowerOf(@base,exponent, exponent); 
    Assert.Equal(expected, result); 
} 

このようにすれば、大きなクラスでより読みやすいテストができます。

+0

ありがとうございます。 1つ目の理由で他の1つを答えとしてマークしました。 – RecursEve

関連する問題