测试驱动开发理解问题

Test Driven Development Understanding Problems

也许有人可以帮助我理解 "Test Driven Development" 方法。我自己尝试了下面的例子,我不知道我的理解问题在哪里。

假设我们需要一个函数返回两个数字 a 和 b 的和

为了确保函数正常工作,我编写了几个测试。就像创建和对象,检查 a 和 b 是否是数字等等..但是正确计算的第一个 "real test" 是以下

a=3
b=3
expected value: 6

TDD方法让我们只需要做那么多的步骤就可以让测试通过。 所以函数看起来像

sum(a, b){
 return 6
}

测试“3+3”将通过。

下一次考试可能是“4+10”。

我会 运行 测试,最后一个测试会失败。真是惊喜...

我将功能更改为

sum(a, b){
 if(a=3 and b=3)
  return 6
 else
  return 14
}

测试会通过!

这样下去……我只会为每个测试添加另一个案例。该函数将通过所有这些测试,但对于其他未列出的情况,它不会通过,结果是一个无效且愚蠢的书面函数。

那么有没有万无一失"trick"不落入这种思维方式呢? 我认为,测试驱动开发非常简单明了。 "break even" 什么时候该说这种测试方式不再可行并切换到正确的解决方案

return a+b;

???

这是一个非常简单的例子,但我可以想象,还有更复杂的函数,显然不像这个那样容易纠正。

谢谢

编写测试的基本思想是了解您的系统何时按预期运行。在测试中,我们做出期望和假设。基本上,我们做以下

  • 设置您的期望
  • 运行代码
  • 对照实际输出检查预期

我们对给定条件设定预期,并根据实际输出进行测试。作为开发人员、产品负责人,我们总是知道系统在任何给定条件下应该如何表现,并相应地编写测试。

例如,对于下面给出的伪代码:

int sum(int a, int b) {
    return a + b;
}

这里的方法 sum 应该 return 参数 a 和 b 的总和。我们知道,

  • 参数应始终为整数。
  • 输出应始终为整数类型。
  • 输出应该是两个数a,b的和。

所以,我们确切地知道它什么时候会失败,我们应该编写测试来覆盖至少 70% 的这些情况。

我是 PHP 人,所以我的示例在 PHP 中。关于提供参数 a、b 的方法。我们有一种叫做数据提供者的东西。我在这里给出 PHP 作为参考,在 PhpUnit the preferred way of passing different argument is to pass it through Dataprovider 中。访问数据提供者示例,您将看到添加示例。

And this goes so on and on ... i will only add another cases for every test. The function will pass every of this tests, but for every other not listed case it will not and the result is an ineffective and stupid written function.

是的,我们尝试涵盖尽可能多的案例。测试越多,我们对代码就越有信心。假设我们编写了一个方法,该方法 returns 数组的子集,每个子​​集都有 4 个唯一元素。现在你如何为它编写测试用例?解决方案之一是计算排列并检查不应超过数组最大计数(每个唯一元素)的数组长度。

Where is the "break even" point when its time to say, that this way of doing tests isn't practicable anymore and switch to the right solution

我们在测试用例中没有收支平衡。但是我们在不同类型的测试用例(单元测试、功能最佳、行为测试)之间做出选择。应实施哪种类型的测试取决于开发人员,并且根据测试类型可能会有所不同。

最好的方法是在项目中实施TDD。除非我们在实际项目中这样做,否则混乱将一直存在。我自己很难理解 Mock 和 Expectations。这不是一夜之间就能学会的东西,所以如果你不明白某些事情是正常的。自己尝试一下,给自己一些时间,和朋友一起做实验,不要筋疲力尽。永远保持好奇心。

如果您对此仍有疑问,请告诉我们。

TDD 工作流有一个由 3 部分组成的周期 ("red,green,refactor"),不要跳过第三部分很重要。例如,在您的第二个版本之后:

sum(a, b){
 if(a=3 and b=3)
  return 6
 else
  return 14
}

你应该看看这个并问:有没有更简单的写法?嗯,是的,有:

sum(a, b){
 return a+b
}

当然,这是一个不切实际的小例子,但在实际编码中,这第三步将指导您将代码细化为编写良好、经过测试的最终版本。