5

一些开发人员对基于示例的测试的 TDD 争论的一个警告是,可能缺少每个有效的输入处理。

让我们举一个简单的例子,这些开发人员可能会争论:

编写一个将两个数字相加的程序。

Bob,一位开发人员开始编写第一个测试:
给定 1 + 3,则结果为 4
实现:def add(x: Int, y: Int) = 4
很好,它通过了。

现在第二个测试:
给定 2 + 2,那么结果是 4。实现仍然相同:def add(x: Int, y: Int) = 4

所以其他开发者会过来告诉他:

“现在您看到 Bob,基于示例的测试对于您糟糕的 2 个示例是不够的!
您没有测试每个输出并查看您的实际实现,对于结果与 4 不同的其他输入,它将失败!
现在,听听我们并开始编写一些基于属性的测试来覆盖所有有效输入。
所以让我们从交换性测试、关联性等开始,这些都是特定于加法的:加法的属性!”

但是但是但是.... Bob 的 TDD 实践真的很糟糕!
确实,他想应用三角测量,但他编写了一个已经成功的测试,因为不需要更改实现!

要导致三角剖分,应该编写一个失败的测试。而三角剖分是TDD实践的万能钥匙之一。
它允许主要步骤:重构,因为您应该管理导致 2 个不同结果的两条路径!

=> 只要测试变得具体,代码就会因为重构而变得更加通用。

所以我的问题是:
如果我们通过良好的三角测量实践来实践严格的 TDD,那么使用基于属性的测试的真正好处是什么,断言在 99% 的情况下已经被良好的 TDD 覆盖的不变量是什么?
确实,假设开发人员具有良好的智商并构建有意义的实现;)

我的例子取自那些幻灯片

4

2 回答 2

5

当边缘情况很难找到或者程序员很容易错过一个时,基于属性的测试非常有用。例如,我在实现 hirschberg 算法时使用了它。没有明显的方法可以将算法划分为更小、更简单、易于 TDD 测试的部分。并且很难手工制作涵盖所有可能算法路径的输入。最好的方法是生成大量不同的输入来覆盖所有路径。当自动检查发现错误时,将特定输入添加到回归测试中

于 2015-06-24T08:43:03.437 回答
1

如果您练习TDD,您就会知道这是一种思考和进行设计的方式,而不是测试。

TDD 起源于增量的,主要是基于状态的单元测试。然后 交互风格(即,mockist-styleLondon-style)TDD 改变了我们对代码设计代码的看法。

基于属性的TDD 也有机会改变我们设计代码的方式。我们没有生成示例来推动我们的设计,而是使用属性。这导致更少的测试更易于维护,测试覆盖率更高。

另一方面,它比基于示例的 TDD 更难,需要更多思考。

于 2016-12-08T04:33:49.377 回答