单元测试中可以有循环吗?单元测试中的循环
我的方法返回一个IEnumerable<IEnumerable>
,我想单元测试这个逻辑IEnumerable<IEnumerable>
创建。基本上我想测试IEnumerable
中元素的计数是否与预期一致。
我找不到一个替代方法来测试内部IEnumerable
没有循环语句。请让我知道这是不是一个好习惯。
单元测试中可以有循环吗?单元测试中的循环
我的方法返回一个IEnumerable<IEnumerable>
,我想单元测试这个逻辑IEnumerable<IEnumerable>
创建。基本上我想测试IEnumerable
中元素的计数是否与预期一致。
我找不到一个替代方法来测试内部IEnumerable
没有循环语句。请让我知道这是不是一个好习惯。
没有技术上的原因,你不能这样做。您可以在单元测试中使用多个Assert语句。在循环中使用Assert语句只是在测试中使用多个Assert语句的简便方法。
但是,有些人认为在单元测试中应该只有一个Assert语句。
我个人不同意 - 我认为一个测试应该测试单一的东西 - 为了做到这一点,有时您可能需要多个Assert语句。
如果你的方法返回商品的IEnumerable,每个产品包含Color的的IEnumerable,那么我认为下面的测试是为罚款:
[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);
一个原因,以避免书写测试中的一个循环就是让测试一目了然,简洁易读。由于您使用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的所有项目属性长度相等且含有 “一” 所有项目字符串,但是:< “ABC”, “猫”,“位”,“帽子”>
但通过如果您更改“位”为“蝙蝠”。
这本书的xUnit测试模式:重构测试代码 杰拉德梅萨罗斯
有许多问题的答案,如你的。
+1,用于暗示使用NUnit约束,但是我建议您可能想要将长度和“包含”约束拆分为单独的测试或至少单独的断言。 – 2017-08-10 17:40:52
是的,你可以在单元测试中有循环,但要谨慎。如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件事情之一。计数器大于大于大于,并且所有进行评估的方法应该一致。
感谢您的回复。术语“可接受的”意味着以敏捷的方式做到这一点是否是一种好的做法。 – Shankar 2011-05-01 10:02:57
我认为我的答案中的测试是“可以接受的”,原因如下:1)测试“单一事物”(所有产品都有一些颜色)。 2)它简单易读。 – 2011-05-01 10:04:36
好吧..那就是我所需要的。我问这个问题是因为有人说我们在每个测试中只需要一个Assert,所以我想从他们那里知道我们如何去测试这个方法:) – Shankar 2011-05-01 10:06:46