当尝试使用TDD编写有意义的测试时,什么时候停止



我很难找到何时停止使用TDD编写测试用例。

假设a必须编写一个只接受某些字符串的方法,它只能接受字符串['red', 'green', 'blue'],它是必需的,不能为空。

我编写第一个失败的测试,使其变为绿色,以此类推,直到我有了测试用例:

it('should accept red input', () => { /*...*/ }
it('should accept green input', () => { /*...*/ }
it('should accept blue input', () => { /*...*/ }
it('should not accept null input', () => { /*...*/ }
it('should not accept empty input', () => { /*...*/ }

在这一点上,一切都在过去,现在我应该到此为止,还是应该在Purple失败的情况下添加一个测试?添加此测试有意义吗?如果是的话,我仍然可以说出其他10种颜色来测试,我应该也考虑一下吗?

这个例子很简单,但有些Regex有无限组合的案例,我知道这可能是一个问题,而且由于时间限制,我无法添加我能想到的所有测试案例。这些都是最糟糕的,因为我不知道什么时候该停止编写测试代码,也不知道何时该适可而止。

我知道我对此没有具体的答案,但我想听听经验,什么在大多数情况下有效。

通常,您希望测试输入类,而不是特定的输入,除非您已经知道特定的输入将产生您需要通过测试来覆盖的特定情况。

在你的例子中,我将把它分解为四个测试:

  1. 应接受预期输入空间中的颜色,例如"红色">
  2. 不应接受不在预期输入空间中的颜色,例如"紫色">
  3. 不应接受空输入
  4. 不应接受null输入

您是对的,通过解析,输入空间是巨大的,覆盖的案例比实际测试的要多。在这种情况下,我会选择一些常见的情况(空/空输入、明确预期和意外的输入等),并尝试思考输入可能未被归类为(非)预期的特定场景。也许有两种颜色"红色"one_answers"红色",你想测试函数是否同时覆盖这两种颜色或其中一种,但不覆盖另一种。在这种情况下,具体的颜色并不重要,只是其中一种包含另一种。

这里有一个很好的答案:是否存在过度的单元测试?

简而言之,您要考虑失败的概率,并将其与编写自动化测试用例的成本进行权衡。

在你的情况下,你可以测试另一种颜色,看看它是否正确地拒绝它。但在所有情况下测试都是不必要的,也是不可能的。

如果您开始接收某个值的重复错误,您可能需要将其添加到测试中。否则将进行边界检查(空或无,行为正确,一次失败)

此时一切都在过去,现在我应该到此为止,还是应该在Purple失败的情况下添加一个测试?添加此测试有意义吗?如果是的话,我仍然可以说出其他10种颜色来测试,我应该也考虑一下吗?

在不列举整个世界的情况下改进对测试对象的评估的一种方法是基于属性的测试。Scott Wlaschin写了一篇很好的技术介绍。

Kent Beck以提请注意测试和实现之间的数据重复而闻名,J.B.Rainsberger建议;删除重复";工作时,数据倾向于向测试移动。那这意味着什么呢?

在您的情况下,听起来您可以将测试对象分为两部分——一部分看起来像是颜色名称的数据库(地图、查找表),另一部分是在给定颜色名称数据库的情况下做一些有趣事情的逻辑。

对于后一部分,你最终会得到像";给定一个[红、绿、蓝]的数据库,当输入为紫色时,受试者是否采取非彩色路径;给定一个[红、绿、蓝、紫]的数据库,当输入为紫色时,受试者是否采用"即是即是"的路径;。

这就让你不得不担心数据库了。你需要注意的是,简单地测试你在两个不同的地方键入了相同的数据并不是特别有价值。

你也可以考虑Beck 的观察结果

我得到的是有效的代码,而不是测试,所以我的哲学是尽可能少地测试,以达到给定的置信水平

请记住,投入测试的时间就是没有投入其他地方的时间。有时,正确的做法是发货,然后在您了解了一些关于它应该如何工作的新知识后再回到代码中。

最新更新