メソッドが正しいIEnumerable
を返すかどうかを確認する単体テストがあります。このメソッドは、yield return
を使用して列挙型を構築します。列挙可能なクラスは次のとおりです。
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);
...、アサーションは失敗します。
PythonのIEnumerable
関数 に類似したZip
の拡張メソッドを作成し(2つのIEnumerableを組み合わせてペアのセットにします)、これを試しました。
foreach(Token[] t in expected.Zip(actual))
{
Assert.AreEqual(t[0], t[1]);
}
出来た!では、これら2つのAssert.AreEqual
sの違いは何ですか?
Assert.AreEqual
は、手元にある2つのオブジェクトを比較します。 IEnumerable
sはそれ自体が型であり、一部のコレクションを反復処理するメカニズムを提供しますが、実際にはそのコレクションではありません。元の比較では2つのIEnumerable
sを比較しましたが、これは有効な比較ですが、必要なものではありません。 2つのIEnumerable
sが列挙するものを比較する必要がありました。
これが2つの列挙型を比較する方法です。
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
メソッドよりもコードが少ないかどうかはわかりませんが、それは非常に簡単です。
それを見つけた:
Assert.IsTrue(expected.SequenceEqual(actual));
代わりにCollectionAssert
クラスを使用することを検討しました...コレクションで等価チェックを実行することを意図していると考えていますか?
補遺:
比較される「コレクション」が列挙型である場合、単純にそれらを「new List<T>(enumeration)
」でラップすることが比較を実行する最も簡単な方法です。もちろん、新しいリストを作成するとオーバーヘッドが発生しますが、単体テストのコンテキストでは、これはそれほど問題にならないと思いますか?
あなたが望む平等を主張する最も簡単で明確な方法は、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.
reallyテストが失敗した場合や、テストが失敗した場合にこのように実行できたことを喜ばしく思います-デバッガをブレークアウトしなくても、何が問題なのかを知ることさえできます。最初に失敗するテストを書きますよね? ;-)
AreEquivalent
を使用して等価性をテストしている場合、エラーメッセージはさらに役立ちます(順序は関係ありません)。
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).