2011-02-08 9 views
3

私は現在のプロジェクトでTDDを勉強して実験しています。 テストで多くのアサーションを複製する必要があることに気付きました。ここ 状況です:私は2つのコンストラクタ最初のものでOrderクラスを持っている デフォルトで、 もう一つは、私は割り当てがうまくユニットテストで重複がアサートされる

Assert.IsTrue(o.CustomerId == 5 && o.TypeId == 3 && amount == 500) 
に働いていることを確認しています3つのparams OrderTestsクラスで

Order(int customerId, int typeId, decimal amount) 

を持っています

オーダーの作成は複雑なプロセスなので、オーダーサービスクラスには以下のオーダー作成メソッドがあります。

Order CreateOrder(int cusotmerId, int typeId, int amount, moreParams...) 

OrderServiceTestsクラスは、このメソッドのテストを持って、私は注文がCreateOrderサービスで正しく作成されていることを確認するために、同じアサーションを使用する必要があります。

Assert.IsTrue(o.CustomerId == 5 && o.TypeId == 3 && amount == 500) 
  1. それがテスト中に、このような重複を持ってしても大丈夫ですか?
  2. テストで同じアサーションを持つメソッドを抽出するのは意味がありますか?あるいは、そのようなメソッド抽出によってテストが判読不能になるのですか?
+0

私が理解する限り、あなたはオブジェクトの作成をテストしようとしています。なぜあなたはそれをする必要がありますか?複雑なロジックはありますか? – Andrey

+0

私が書いたように、それはオブジェクトグラフを作成する複雑なプロセスです – Danil

+0

Orderは純粋な値のオブジェクト/データ構造ではないと仮定します(この場合、失敗/修正するのはあまりにも些細かもしれません):ヘルパーメソッド 'AreAttributesEqual expectedOrder、actualOrder、listOfAttributesToCompare) 'を使用してリフレクションを使用します。すべてのプロパティを常に比較したい場合は、さらに簡単です。 – Gishu

答えて

4

オブジェクトを作成する方法が複数ある場合は、それぞれの作成メソッド(つまり、ファクトリメソッドと同様にパラメータ化されたコンストラクタ)に対してオブジェクトの状態をテストすることができます。したがって、アサーションを複製することは理にかなっています。

実証コードだけでなくテストでも重複が見つかった場合は、テストパスを実行した後にリファクタリングする際に(マントラ:赤 - 緑 - リファクタリングを常に覚えておいてください。抽出メソッドリファクタリングを使用します。

例のように1つのAssertステートメント内で複数の条件をチェックすると複雑になります。テストの可読性が低下し、条件のいずれかが失敗した場合に原因を見つけることが難しい場合があります。

1

はい、ユニットテストでコードが重複することがよくあります。しかし、この重複は価値があります。アイデアは、2つの方法で同じことを書いても、同じミスを繰り返すことはないということです。つまり、あなたは愚かなバグをたくさん見つけます。 (あなたのユニットのテストコードには、おそらく半分があります。)あなたのコードからユニットテストを自動的に生成すると、すべてのコードが重複してしまいます。

3

複数のテストで同じオブジェクト検証を実行する必要がある場合は、これらのAssertを共通のメソッドに分割すると、重複を減らすのに適しています。上の例では、AssertObjectIsValidというメソッドを用意して共通コードをそこに移動することができます。

あなたの例に関連するもう1つのことはアサートです。 1つのAssertで複数のチェックを組み合わせることで、不具合の原因となった不具合を特定することがより困難になります。あなたがアサート独立して、それぞれのメッセージを提供にこれらを分割した場合、それは(あなたがそのようなCruiseControl.Netとして継続的インテグレーションサーバを使用する場合は特に。)はるかに簡単にエラーを追跡ようになりますあなたの例を変更:

Assert.IsTrue(o.CustomerID == 5, "CustomerID doesn't match expected"); 
Assert.IsTrue(o.TypeId == 3, "TypeID doesn't match expected"); 
Assert.IsTrue(amount == 500, "Amount doesn't match expected"); 
+3

また、Assert.IsEqual(5, o.CustomerID);を使用すると、アサーションエラーの読みやすさが向上することを明示します。Assert.IsTrue() bcarlso

+0

アサルトの数を減らすために1つのアサートで複数のチェックを書きました。それ以外の場合は、オブジェクトの作成だけで8つのアサートを行います(ステータス履歴アイテムを内部履歴コレクションに追加するため)。おそらく、それは8つのアサートを持つことは問題ではないでしょう。 – Danil

+0

@bcarlso - IsEqualの使用についての良い点。 @ダニル - 検証する数が多い場合、多数のアサーションを持つことは問題ありません。 Assertsのセットを共通のメソッドにグループ化すると、行数を減らすのに役立つことがあります。 – Pedro

関連する問題