2012-02-11 20 views
3

私は単体テストの周りに頭を抱えようとしていましたが、単体テストの処理には戻り値がパラメータの束に依存しているということに取り組んでいます。そこに多くの情報は、しかしだ、それは...複数の入力によるユニットテスト

は、次の点を考慮してビット圧倒的です:

私は価格のコレクションを持つクラスArticleを、持っています。

public class Article 
{ 
    public string Id { get; set; } 
    public string Description { get; set; } 
    public List<Price> Prices { get; set; } 

    public Article() 
    { 
     Prices = new List<Price>(); 
    } 

    public Price GetCurrentPrice() 
    { 
     if (Prices == null) 
      return null; 

     return (
      from 
      price in Prices 

      where 

      price.Active && 
      DateTime.Now >= price.Start && 
      DateTime.Now <= price.End 

      select price) 
      .OrderByDescending(p => p.Type) 
      .FirstOrDefault(); 
    } 
} 

PriceType列挙型とPriceクラス:

public enum PriceType 
{ 
    Normal = 0, 
    Action = 1 
} 

public class Price 
{ 
    public string Id { get; set; } 
    public string Description { get; set; } 
    public decimal Amount { get; set; } 
    public PriceType Type { get; set; } 
    public DateTime Start { get; set; } 
    public DateTime End { get; set; } 
    public bool Active { get; set; } 
} 

私はGetCurrentPriceメソッドの単体テストを作成するにはいくつかのルールに基づいて、現在の価格を決定する方法GetCurrentPriceを持っています。基本的には、発生する可能性のあるすべてのルールの組み合わせをテストしたいので、完全なカバレッジを得るためにさまざまな価格の組み合わせを含む複数の記事を作成する必要があります。

私はこのようなユニットテスト(擬似)と思っています:

[TestMethod()] 
public void GetCurrentPriceTest() 
{ 
    var articles = getTestArticles(); 
    foreach (var article in articles) 
    { 
     var price = article.GetCurrentPrice(); 
     // somehow compare the gotten price to a predefined value 
    } 
} 
  • 私は「複数の邪悪されている主張する」ことを読んだが、私は彼らがに を必要としませんすべての条件をここでテストしますか?または条件ごとに別のユニット テストが必要ですか?

  • 単体テストに一連のテストデータを提供するにはどうすればよいですか? リポジトリを模擬すべきですか?そのデータには の期待値も含まれていますか?

答えて

3

この例ではリポジトリを使用していないため、何かを模擬する必要はありません。

[TestMethod] 
public void Foo() 
{ 
    // arrange 
    var article = new Article(); 
    // TODO: go ahead and populate the Prices collection with dummy data 


    // act 
    var actual = article.GetCurrentPrice(); 

    // assert 
    // TODO: assert on the actual price returned by the method 
    // depending on what you put in the arrange phase you know 
} 

ので、あなたが唯一の可能性のある各入力に対してarrangeassertフェーズを変更するだろう他のユニットテストを追加することができます上:何あなたができることは異なる可能な入力のための複数のユニットテストを作成することです。

+0

この場合の「ユニット」とは何ですか?私は 'GetCurrentPrice'が適切に動作するかどうかを知りたいだけです。すべての異なる入力は「ユニット」であり、メソッドの正確さは、これらのユニットテストがすべて成功したことに依存しますか?それともメソッド自体が単位ですか? – diggingforfire

+0

@diggingforfire、 'unit'はありません。しかし、それはあなたのコードが 'ユニット 'が存在しないように設計されているからです。あなたの 'Article'クラスは2つのことを行います:それはいくつかのデータを保持するプロパティを持ち、このデータを操作するメソッドを含んでいます。だからあなたはユニット2を単体でテストすることはできません。これらの責任を分けたければ 'GetCurrentPrice'を独立したリポジトリクラスに定義しておくと、' Article'インスタンスを引数として取ることができます。 –

+0

それは貧血ドメインモデルにつながりませんか?私はその論理を含むために 'Article'自体を好むでしょう。 – diggingforfire

2

複数のアサートは必要ありません。それぞれ単一のアサートで複数のテストが必要です。

+0

私はここに同意しません。私はあなたが同じ結果を期待している限り、テストデータを組み合わせることができると思います。反復パターン内で1回のテストで同じことを達成できるときに、私が100単位テストを書く理由はありません。これは、それぞれのテスト結果が同じでなければならないと仮定しています。ここでの例は、メソッドに渡された各キーのテストデータとして使用されたキー値のペアの辞書です。メソッドの戻り値はキーの値のペアの値でなければなりません。なぜこれが効果的でないのかはわかりません。 – tsells

+0

今日の終わりには同じデータ評価が行われ、失敗した場合はどうにかして理由を把握する必要があります。デバッガを起動してテストを調べます。同じ結果 - 維持するのがはるかに容易..... – tsells

+0

@tsells:私は単一のユニットテストを作成し、次に2番目のユニットテストを作成してから、私はリファクタリングを開始します。私は反復テストのレベルに非常によく慣れているかもしれませんが、1つのテストが失敗すると残りのテストが実行されないという欠点があります。 –

2

各起動条件と単一アサートの新しいテストf.e。

[Test] 
public void GetCurrentPrice_PricesCollection1_ShouldReturnNormalPrice(){...} 

[Test] 
public void GetCurrentPrice_PricesCollection2_ShouldReturnActionPrice(){...} 

とも私はあなたがdatadrivenテストが必要だと思う私は、パターン

MethodName_UsedData_ExpectedResult() 
+0

だから、可能性のあるすべての入力に対してテストを行い、それはそれぞれの出力ですか?それは論理的に聞こえる。すべてを設定するには手作業で多くのコーディングが必要になると思われます。そのようなデータを簡単にテストに提供する方法はありますか? – diggingforfire

+0

私が興味を持っているのは、すべてをテストすることではない(ほとんど不可能)ということです。境界線に焦点を当てて特別に注意を払うべきである(例えば、日付は異なるが価格は異なる)。よくあることはたくさんテストする価値がありません。たとえば、有効なPriceCollectionを作成するために工場を頻繁に使用しますが、いくつかのことをさらにコード化する必要がありますが、ソリューションをリファクタリングするときに感謝している単体テストの魔法使いで覆われています。 – Ivan

+0

Resharperはユニットテストのそのパターンのためにあなたに叫びます。ちょうど好奇心が強い - なぜそこにメソッド名が必要なのですか?テスト中にどのメソッドが呼び出されているのか分かりませんか? – tsells

2

を使用するユニットテストのための境界

をテスト。 vstsにはDatasourceと呼ばれる属性があり、これを使用してテストメソッドを複数のテストケースに送信できます。複数のアサートを使用しないでください。ここに1つのMSDNリンクがあります。http://msdn.microsoft.com/en-us/library/ms182527.aspx

希望すると、これが役に立ちます。

+0

なぜデータ駆動ですか?これはデータベースのテストではありません。 – tsells

+0

複数の入力を持つメソッドをテストする必要がある場合は、データ駆動型テストを使用します。どのような方法でもかまいません。 –