2009-06-01 12 views
35

私はメソッドが正しいIEnumerableを返すかどうかをチェックするユニットテストを持っています。このメソッドは、yield returnを使用して列挙型を作成します。それはの可算であるというクラスは以下の通りです:Assert.AreEqualは、2つの汎用IEnumerablesの間の等価性をどのようにして決定しますか?

enum TokenType 
{ 
    NUMBER, 
    COMMAND, 
    ARITHMETIC, 
} 

internal class Token 
{ 
    public TokenType type { get; set; } 
    public string text { get; set; } 
    public static bool operator == (Token lh, Token rh) { return (lh.type == rh.type) && (lh.text == rh.text); } 
    public static bool operator != (Token lh, Token rh) { return !(lh == rh); } 
    public override int GetHashCode() 
    { 
     return text.GetHashCode() % type.GetHashCode(); 
    } 
    public override bool Equals(object obj) 
    { 
     return this == (Token)obj; 
    } 
} 

これは方法の関連する部分である:

foreach (var lookup in REGEX_MAPPING) 
{ 
    if (lookup.re.IsMatch(s)) 
    { 
     yield return new Token { type = lookup.type, text = s }; 
     break; 
    } 
} 

私はactualにこのメソッドの結果を保存する場合は、別の列挙expectedを行い、このように比較してください。

Assert.AreEqual(expected, actual); 

...アサーションが失敗します。

私は(それはペアのセットに2 IEnumerablesを兼ね備え)Python's zip functionに似てIEnumerableための拡張メソッドを書いて、この試みた:それは働いた

foreach(Token[] t in expected.zip(actual)) 
{ 
    Assert.AreEqual(t[0], t[1]); 
} 

を!では、これら2つの違いは何ですか?Assert.AreEqual

+1

@Jasonベイカー:あなたは(順番は関係ありません)等価性をテストするためにAreEquivalentを使用している場合;-)

は、エラーメッセージは、より便利取得この間違ったを服用しないでくださいあなたは、このような質問をしなければならないという事実は、あなたが物事を複雑にしていることを意味するかもしれないと考えましたか? –

+1

Erm ...いいえ、実際にはありません。私が物事を複雑にしているところに向かって私を指摘できますか? –

+0

また、私は "text.GetHashCode()%type.GetHashCode();"を使用すると確信していません。 GetHashCode()の戻り値としては良い考えです... –

答えて

25

Assert.AreEqualは、手元の2つのオブジェクトを比較する予定です。 IEnumerableは、それ自体の型であり、いくつかのコレクションを反復するメカニズムを提供します...しかし、実際にはそのコレクションではありません。あなたの元の比較は2つの比較されたIEnumerableです。これは有効な比較ですが、必要なものではありません。 と比較する必要があったのは、2つのIEnumerableが列挙しようとしていたものです。ここで

は、私が2 enumerablesを比較する方法である:

Assert.AreEqual(t1.Count(), t2.Count()); 

IEnumerator<Token> e1 = t1.GetEnumerator(); 
IEnumerator<Token> e2 = t2.GetEnumerator(); 

while (e1.MoveNext() && e2.MoveNext()) 
{ 
    Assert.AreEqual(e1.Current, e2.Current); 
} 

私は上記があなたの.Zip方法より少ないコードであるかどうかわからないが、それを取得と同じくらい簡単です。

+0

これは意味があります。 2つのIEnumerablesオブジェクトをオブジェクトごとに比較する方法はありませんか? –

+0

私はちょうどwhileループを使います。私は例で私の答えを更新しました。 – jrista

+0

私は別のやり方が見つかった、と簡単です。なぜ私のコードがうまくいかなかったのかを示したので、これを受け入れます。 :-) –

86

はそれを見つけた:

Assert.IsTrue(expected.SequenceEqual(actual)); 
+0

ニースが見つかりました!私はSequenceEqual()拡張があったことさえ知りませんでした。タイ! – jrista

+0

ありがとうございました。私のループを保存しました;-) –

+3

これは、テストが失敗したときにどの要素が不等であったかについての情報を教えてくれません。失敗したと伝えます。 jerryjvlによって提案されたCollectionAssertメカニズムは、より豊富な失敗情報を提供します。 – bacar

47

あなたはコレクションに平等のチェックを実行するために意図されていることを考えると...代わりにCollectionAssertクラスを使用して考えがありますか?

補遺:
比較されている「コレクション」は、列挙されている場合は、単に「new List<T>(enumeration)」でそれらをラップして比較を実行するための最も簡単な方法です。新しいリストを作成すると、もちろんオーバーヘッドが発生しますが、単体テストの文脈では、これはあまり重要ではありません。

+0

CollectionAssertのすべてのメソッドはICollectionと比較するように設定されています。私はIEnumerablesを持っています。それらをICollectionsに変更する簡単な方法はありますか? –

+0

そのような場合、私は通常、新しいリスト(列挙型)ですばやくまとめて、比較を実行できます。ユニットテストの文脈でオーバーヘッドが問題になりやすいようなものではありません。 – jerryjvl

+6

CollectionAssertを使用するときは、両方の引数で.ToArray()を実行してください。 – MEMark

18

私はあなたが欲しい平等を主張する最も簡単かつ明確な方法はjerryjvlによって答えの組み合わせだと思うとMEMarkで彼のポストにコメント - 拡張メソッドでCollectionAssert.AreEqualを兼ね備え:

CollectionAssert.AreEqual(expected.ToArray(), actual.ToArray()); 

これは、より豊富なエラーを与えますOPによって提案されたSequenceEqualの回答よりも情報があります(予期しない要素が見つかったことがわかります)。例えば: - 時にはあなたもデバッガを抜け出すすることなく、間違っているのかを知ることができます - とちょっとあなたがしている

IEnumerable<string> expected = new List<string> { "a", "b" }; 
IEnumerable<string> actual = new List<string> { "a", "c" }; // mismatching second element 

CollectionAssert.AreEqual(expected.ToArray(), actual.ToArray()); 
// Helpful failure message! 
// CollectionAssert.AreEqual failed. (Element at index 1 do not match.)  

Assert.IsTrue(expected.SequenceEqual(actual)); 
// Mediocre failure message: 
// Assert.IsTrue failed. 

あなたはあなたのテストが失敗したとき/場合は本当にはあなたがそれをやったこの方法を喜ばだろうTDDを正しくやっているので、最初に不合格のテストを書くのですよね?

CollectionAssert.AreEquivalent(expected.ToList(), actual.ToList()); 
// really helpful error message! 
// CollectionAssert.AreEquivalent failed. The expected collection contains 1 
// occurrence(s) of <b>. The actual collection contains 0 occurrence(s). 
関連する問題