您是否在实际项目中使用过Quickcheck [已关闭]
Quickcheck及其变体(甚至在Java中也有一个)似乎很有趣。然而,除了学术兴趣之外,它在实际的应用程序测试中真的有用吗(例如,GUI应用程序或客户端/服务器,甚至采取StackOverflow本身)?您使用类似测试发生器的任何经验都值得赞赏。
Quickcheck及其变体(甚至在Java中也有一个)似乎很有趣。然而,除了学术兴趣之外,它在实际的应用程序测试中真的有用吗(例如,GUI应用程序或客户端/服务器,甚至采取StackOverflow本身)?您使用类似测试发生器的任何经验都值得赞赏。
是的,好吧。实际上没有,但我在最初开发QuickCheck的人的指导下学习,他是一个非常有趣的人。
早在2004年,我们被迫使用QuickCheck来测试我们的Haskell程序,这是好与坏的结合。主要是因为Haskell本身有点令人生畏,但当你让它工作时,它永远不会那么美妙。
从那时起,John完善了他多年前写的东西,实际上帮助Ericssion测试了他们复杂的电信硬件,他发现了大约2000万行代码中的错误,通过他的方法将其减少到三个步骤。他是一个伟大的演讲者,所以听他介绍他做得很好总是很高兴,但总而言之,他用QuickCheck做的事情对我来说是新的。所以我问他,他有什么兴趣把这个推向市场。他对这个想法持开放态度,但当时他的业务(基于QuickCheck)相对较新,因此他会关注其他领域。现在是2007年。我的观点是,你可以从QuickCheck中学习,即使你最终不会使用它。
但什么是快速检查?这是一个组合测试框架,也是测试程序的有趣方式。微软研究院的人已经建立了Pex,这有点类似。Pex 通过检查您的 IL 自动生成测试。但是,John 会为函数的可能输入和测试属性编写一个生成器。房产是可以很容易地测试的东西,而且它更正式。例如,反转列表?好吧,反转列表与将列表分成两半是一回事,将它们分别反转,然后以相反的顺序连接两个反转的一半。
1,2,3,4 // original
1,2 3,4 // split into A and B
2,1 4,3 // reverse A and B
4,3,2,1 // concat B and A
这是使用称为规范的QuickCheck进行测试的一个很好的属性,结果非常令人惊讶。
Pex很好,但不像QuickCheck那么酷,Pex简化了事情,QuickCheck做到了,但写一个好的规范需要付出很多努力。
QuickCheck的强大之处在于,当它遇到故障时,它会将导致测试失败的输入减少到尽可能小的形式。给你一个详细的描述,说明是什么状态进展导致你的测试失败。与其他测试框架相比,这些框架将尝试以蛮力的方式破坏代码。
这是由于您编写测试规范的方式而成为可能的。QuickCheck依靠伪随机性来发明输入,正因为如此,它能够回溯并找到无法通过测试的非常小的输入。
编写 QuickCheck 属性需要做更多的工作,但最终结果是更好的测试。正如John自己所说,70%的错误是通过单元测试捕获的,但另外30%的错误会导致你的程序崩溃。QuickCheck正在测试最后30%。
我做了一个真正的Haskell问题,它涉及离散事件模拟。因此,我编写了一个基于延续 monad 的 DES 库,以及 MVar 和通道的等效项。我需要检查这是否正常工作,所以我编写了一堆QuickCheck属性来证明,例如,写入通道的两个并发数据流将正确合并而不会丢弃任何内容。
我还使用 QuickCheck 来记录和验证我的 Ranged Sets 和 Decimal 库中的属性。
根据我的经验,QuickCheck有时很棒。如果你能以简洁的方式总结一个重要的属性,尽管提供该属性的算法是毛茸茸的,那么QuickCheck是一个巨大的胜利。另一方面,我经常发现算法等效于我要验证的属性。在这种情况下,我寻找更简单的属性。例如,假设函数“foo”应该是非严格单调的。然后你可以写
prop_fooMonotonic x y = (x > y) ==> (foo x >= foo y)