Assert.AreEqual如何确定两个genericsIEnumerables之间的相等性?
我有一个unit testing来检查一个方法是否返回正确的IEnumerable
。 该方法使用yield return
来构build枚举。 它是一个枚举的类如下:
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);
…,断言失败。
我为IEnumerable
编写了一个扩展方法,类似于Python的zip
函数 (它将两个IEnumerables组合成一组对),并尝试这样做:
foreach(Token[] t in expected.zip(actual)) { Assert.AreEqual(t[0], t[1]); }
有效! 那么这两个Assert.AreEqual
什么区别呢?
Assert.AreEqual
将会比较两个对象。 IEnumerable
s是types本身,并提供了一个机制来迭代一些集合…但他们实际上不是那个集合。 您的原始比较比较两个IEnumerable
s,这是一个有效的比较…但不是你所需要的。 您需要比较两个IEnumerable
的列举 。
这是我如何比较两个枚举:
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
方法less,但是它只是简单而已。
find了:
Assert.IsTrue(expected.SequenceEqual(actual));
你考虑过使用CollectionAssert
类吗?考虑到它是为了对集合执行平等检查吗?
附录:
如果比较的“集合”是枚举,那么简单地用“ new List<T>(enumeration)
”包装它们是执行比较的最简单的方法。 构build一个新的列表当然会带来一些开销,但是在unit testing的背景下,我希望这不应该太重要?
我认为最简单最明确的方式来expression你想要的平等是由jerryjvl的答案和由MEMark评论他的职位的组合 – CollectionAssert.AreEqual
与扩展方法的结合:
CollectionAssert.AreEqual(expected.ToArray(), actual.ToArray());
这比OPbuild议的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.
当你的testing失败的时候,你会很高兴你这样做 – 有时你甚至可以知道什么是错的,而不必打破debugging器 – 嘿,你正在做TDD,所以你先写一个失败的testing,对? 😉
如果您使用AreEquivalent
来testing等同性(顺序无关紧要),则错误消息会更有帮助:
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).