如何使用TDD指定循环?

时间:2015-04-14 08:53:50

标签: unit-testing tdd

我经常发现我不确定如何测试需要循环的代码。举例来说:

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个项目的输入都将被处理?如何在测试中最好地描绘它?

4 个答案:

答案 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)检查对模拟方法的调用次数。