尝试使用TDD编写有意义的测试时何时停止?

时间:2019-01-31 10:41:50

标签: javascript mocha tdd chai

我正在努力寻找何时停止使用TDD编写测试用例。

假设必须编写一个只接受某些字符串,只能接受['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种颜色进行测试,我是否也应该全部考虑呢?

此示例很简单,但是有些Regexes包含无限组合的情况,我知道这可能是个问题,并且我无法添加所有我认为可以用于时间限制的测试用例。这是最糟糕的情况,因为我不知道何时停止编写测试代码,并找到足够的时间。

我想我对此并没有具体的答案,但是我想从经验中听到大部分时间都是有效的。

3 个答案:

答案 0 :(得分:2)

一个伟大的回答是张贴在这里: Is there such a thing as excessive unit testing?

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

在您的情况下,您可以测试另一种颜色以查看其是否能正确拒绝它。但测试对于所有情况是不必要的,并且不可能的。

如果您开始在某个值上收到重复性错误,则可能需要将其添加到测试中。否则边界检查会做(空或无,正确的行为,一个故障)

答案 1 :(得分:1)

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

在您的示例中,我将其细分为四个测试:

  1. 应该接受在期望的输入空间,例如颜色“红色”
  2. 不应该在预期的输入空间,例如接受颜色不“紫色”
  3. 不应该接受一个空的输入
  4. 不应接受空输入

您说对了,解析输入空间非常大,涉及的案例比实际测试要多。在那种情况下,我会考虑一些常见的情况(空/空输入,明确预期和意外输入等),并尝试考虑将输入误分类为(未预期)输入的特定情况。 也许有两种颜色“红色”和“红色”,并且您想测试该功能可以同时覆盖这两种或一种,但不能覆盖另一种。在这种情况下,特定的颜色并不重要,只需其中一种包含另一种即可。

答案 2 :(得分:1)

  

在这一点上一切都已经通过了,现在我应该将其命名为“一天又一次”,还是应该为紫色失败而添加测试?添加此测试有意义吗?如果是这样,我仍然可以命名其他10种颜色进行测试,我是否也应该全部考虑呢?

基于属性的测试是一种无需对整个世界进行枚举就可以提高对测试主题的评估的方法。 Scott Wlaschin撰写了good introduction to the technique

Kent Beck以引起人们对测试和实现之间的数据重复的关注而闻名,JB Rainsberger建议,作为“删除重复”工作的一部分,数据趋向于朝测试的方向发展。那是什么意思?

在您的情况下,听起来好像您可以将测试对象分成两部分-一部分看起来像颜色名称的数据库(映射,查找表),另一部分则具有一些逻辑,可以根据需要进行一些有趣的操作颜色名称数据库。

对于后一部分,您将得到诸如“给定[红色,绿色,蓝色]数据库”之类的测试,当输入为紫色时,测试对象是否采用了thats-not-a-color路径;给定了一个数据库[红色,绿色,蓝色,紫色]中的一个,当输入为紫色时,测试对象是否采用“原样”的路径。

这使您不必担心数据库。您要注意的事实是,仅测试在两个不同位置键入相同数据并没有特别的价值。

您可能还会考虑来自Beck

的观察结果
  

我从有效的代码而不是测试中获得报酬,所以我的理念是尽可能少地测试以达到给定的置信度

请记住,在测试上花费的时间就是没有在其他地方花费的时间。有时候正确的做法是发布,然后在您了解了有关其工作原理的新知识后,再返回代码。