我们可以在单元测试中使用循环吗?
我的方法返回IEnumerable<IEnumerable>
,我想在创建IEnumerable<IEnumerable>
的地方对这个逻辑进行单元测试。基本上我想测试IEnumerable
中元素的数量是否符合预期。
在没有循环语句的情况下,我无法找出测试内部IEnumerable
的替代方法。如果这是一个很好的做法,请告诉我。
答案 0 :(得分:21)
没有技术理由你不能这样做。您可以在单元测试中使用多个Assert语句。在循环中使用Assert语句只是在测试中使用多个Assert语句的简便方法。
但是,有些人认为在单元测试中应该只有一个Assert语句。
我个人不同意 - 我认为测试应该测试一件事 - 为了做到这一点,有时您可能需要多个Assert语句。
如果你的方法返回一个IEnumerable的产品,并且每个产品包含一个IEnumerable of Color,那么我认为以下测试是正常的:
[Test]
public void All_products_should_have_some_colors()
{
var products = GetProducts();
foreach (var product in products)
{
Assert.IsNotEmpty(product.Colors);
}
}
但是,您需要注意,如果IEnumerable包含0个元素,则循环将永远不会执行任何Assert语句,并且您的单元测试将“通过” - 而您可能会打算失败。
为了解决这种情况,你可以进行单独的测试,确保IEnumerable中有超过0个元素(即GetProducts确实返回了一些产品):
Assert.IsNotEmpty(products);
答案 1 :(得分:8)
避免在测试中编写循环的一个原因是让测试简洁易读。由于您已使用NUnit标记了问题,并且您说您只想测试元素计数是否符合预期,请考虑使用NUnit Constraints制作断言。
例如,
IEnumerable<IEnumerable<char>> someStrings = new[] { "abc", "cat", "bit", "hat" };
Assert.That(someStrings, Has.All.With.Length.EqualTo(3).And.All.Contains("a"));
失败并显示以下消息:
预期:所有项目属性长度等于3,所有项目字符串包含“a” 但是:&lt; “abc”,“cat”,“bit”,“hat”&gt;
但如果你将“bit”改为“bat”,则会通过。
本书xUnit测试模式:重构测试代码 作者Gerard Meszaros
对你这样的问题有很多很好的答案。
答案 2 :(得分:2)
是的,您可以在单元测试中使用循环,但要小心。正如Alex York所提到的,如果你测试一个的东西,循环是可以接受的;即一个期望。
如果你使用循环,那么我建议你必须做两件事:
以下是我测试对象的大于属性的示例。
[Test]
public void TestCompare_XtoY_GreaterThan()
{
int numObjects = mOrderedList.Count;
for (int i = 1; i < numObjects; ++i)
{
for (int j = 0; j < i; ++j)
{
string testDescription = string.Format("{0} is greater than {1} which implies\n {2}\n is greater than\n {3}"
, i, j
, mOrderedList[i], mOrderedList[j]
);
Assert.IsTrue(0 < mOrderedList[i].CompareTo(mOrderedList[j]), testDescription);
Assert.IsTrue(0 < mOrderedList[i].Compare(mOrderedList[i], mOrderedList[j]), testDescription);
Assert.IsTrue(0 < mOrderedList[j].Compare(mOrderedList[i], mOrderedList[j]), testDescription);
Assert.Greater(mOrderedList[i], mOrderedList[j], testDescription);
}
}
}
我在测试设置中使用以下方法测试我的有序列表是否为空
[SetUp]
public void GeneralTestSetup()
{
// verify the iterated sources are not empty
string testDescription = string.Format("The ordered list of objects must have at least 3 elements, but instead has only {0}.", mOrderedList.Count);
Assert.IsTrue(2 < mOrderedList.Count, testDescription);
}
即使在我的循环中我也有多个断言,但所有断言都在测试单个期望:
if i > j then mOrderedList[i] > mOrderedList[j]
迭代级别的测试描述使您获得失败,例如:
10 is greater than 9 which implies
TestActionMethodInfo: [Actions.File, Version=1.0.446.0, File, VerifyReadOnly]
is greater than
TestActionMethodInfo: [Actions.File, Version=1.0.446.0, File, Write]
Expected: True
But was: False
而不只是:
Expected: True
But was: False
关于我的代码的问题/辩论:
我正在测试一件事吗?我在对象中主张4种不同的比较方法,可以说是测试4个不是一个的东西。计数器大于大于大于,并且所有进行评估的方法应该是一致的。