我经常发现我不确定如何测试需要循环的代码。举例来说:
methodUnderTest(inputQueue) {
while (inputQueue.count > 0) {
process(inputQueue.dequeue());
}
}
第一个测试可能如下所示:
processesInput1() {
// Arrange
inputQueue = [a];
// Act
methodUnderTest(inputQueue);
// Assert
Assert.wasProcessed(a);
}
逻辑上的下一个测试是:
processesInput2() {
// Arrange
inputQueue = [a, b];
// Act
methodUnderTest(inputQueue);
// Assert
Assert.wasProcessed(a);
Assert.wasProcessed(b);
}
但到我们到达时:
processesInput3() {
// Arrange
inputQueue = [a, b, c];
// Act
methodUnderTest(inputQueue);
// Assert
Assert.wasProcessed(a);
Assert.wasProcessed(b);
Assert.wasProcessed(c);
}
这一切都开始变得多余了。我曾经听说过有关TDD的一条很好的建议是将测试视为规范。在什么时候测试指定N个项目的输入都将被处理?如何在测试中最好地描绘它?
答案 0 :(得分:4)
我同意你的评估 - 3项感觉就像是一项冗余测试(2项已经足够N项的情况)。我还认为,一旦你对2个项目进行了测试,对于1个项目的测试也是多余的,但当然由于训练有素地使用TDD而结束。
从规范的角度来看,对0项目的测试和对N项目的测试感觉就足够了,因此如果你想保持你的测试集最小,我建议删除1项的测试。
答案 1 :(得分:2)
我建议你重新检查原来的问题。 TDD鼓励您通过指定应该发生的事情,逐步推出实施,一步一步。我建议使用“循环”这个词。在这个(或几乎任何其他)规范中是不必要的。相反,我希望看到一个规范,其中包含#34;所有输入都应该被处理。"现在,队列中的输入数量(如果它是什么)是任意的 - 要求是它们都应该被处理。
如何测试不同数量的输入的选择取决于您对风险是什么(发生问题)以及利益(来自编写额外测试)的专业判断。正如Kent Beck said:
“我得到的代码是有效的,而不是测试,所以我的理念是尽可能少地测试以达到给定的置信水平...... 我怀疑与行业标准相比,这种信心水平很高“
答案 2 :(得分:1)
一般来说,你想测试一个快乐的路径和边界条件。
从数学上讲,你想要涵盖所有等价类。它表示表示一组有意义的用例的输入。例如空,非空和完整队列。
在你的情况下,测试0项和2项就足够了。
答案 3 :(得分:0)
与其他答案一样,测试零和两个参数可能就足够了。但是,您可能想尝试使用1000或更多。什么?
测试在什么时候指定N个项目的输入都将被处理?如何在测试中最好地描绘它?
现在取决于模拟框架是否支持这样的事情,但是在gmock中你可以使用.WillRepeatedly(action)
,在action
中你可以进行额外的处理(比如在你的具体例子中检查数组值。) / p>
如果您使用gmock,您还可以使用.Times(cardinality)
检查对模拟方法的调用次数。