36

Quickcheck及其变体(即使在Java中有一个),似乎很有趣。然而,除了学术兴趣之外,它在真正的应用程序测试中是否真的有用(例如,GUI 应用程序或客户端/服务器,甚至是 StackOverflow 本身)?感谢您对类似测试生成器的任何体验。

4

11 回答 11

48

好吧。实际上没有,但我曾在最初开发 QuickCheck 的人手下学习,他是一个非常有趣的人。

早在 2004 年,我们被迫使用 QuickCheck 来测试我们的 Haskell 程序,它是好坏参半。主要是因为 Haskell 本身有点令人生畏,但当你让它工作时,它的美妙之处就永远不会减少。

从那以后,约翰完善了他多年前写的东西,并帮助爱立信测试了他们复杂的电信硬件,他在大约 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 属性需要做更多的工作,但最终结果是更好的测试。正如约翰本人所说,70% 的错误是通过单元测试捕获的,但导致程序崩溃的是另外 30% 的错误。QuickCheck 正在测试最后的 30%。

于 2009-02-23T09:23:54.043 回答
8

我已经完成了一个涉及离散事件模拟的真正 Haskell 问题。所以我写了一个基于 continuation monad 的 DES 库,以及 MVars 和 Channels 的等价物。我需要检查它是否正常工作,所以我编写了一堆 QuickCheck 属性来证明,例如,写入 Channel 的两个并发数据流将被正确合并而不会丢失任何内容。

我还使用 QuickCheck 来记录和验证我的Ranged SetsDecimal库中的属性。

根据我的经验,QuickCheck 有时很棒。如果你能以简洁的方式总结一个重要的属性,尽管提供该属性的算法很复杂,那么 QuickCheck 是一个巨大的胜利。另一方面,我经常发现算法等价于我要验证的属性。在这种情况下,我会寻找更简单的属性。例如,假设函数“foo”应该是非严格单调的。然后你可以写

prop_fooMonotonic x y = (x > y) ==> (foo x >= foo y)
于 2009-02-24T07:54:03.537 回答
7

我使用 QuickCheck 处理很多个人事务。过去六个月内:

  • 运行 QuickCheck 以测试图像压缩器中的颜色变换和离散余弦变换。

  • 运行 QuickCheck 来测试我为一些数值优化而设计的符号微分模块。

  • 运行 QuickCheck 以测试 Bentley 和 Sedgewick 风格的三元搜索树。

QuickCheck 很少能满足我所有的单元测试需求,但它是一个很好的入门方式——而且 QuickCheck 法律可以制作很好的文档。

于 2009-02-24T02:04:12.360 回答
5

我已经用过很多次了,主要是以直接的方式,主要用于测试协议和解析器实现。

但是,从我的个人经验来看,这是不那么微不足道的一点:http ://www.haskell.org/haskellwiki/QuickCheck_as_a_test_set_generator

于 2009-02-23T09:52:43.117 回答
5

ScalaCheck(Scala 的 QuickCheck)用于测试Functional Java,这是一个库,除其他外,实现了 Java 的 QuickCheck

于 2009-02-24T02:10:02.987 回答
3

AFAIK XMonad 使用 QuickCheck 进行了广泛测试

于 2011-06-23T09:19:36.190 回答
2

我只在生产环境中使用 Haskell 开发小助手工具。主要是因为我是我认识的唯一一个阅读 Haskell 的开发人员。虽然我广泛使用了 QuickCheck,但我对 C# 中没有类似的东西感到非常恼火。所以我决定尝试自己写。我也查看了 Pex,但发现用于查找最小输入的程序探索技术不如 QuickCheck 那样有趣。

于 2009-08-10T09:45:25.383 回答
2

我使用 QuickCheck 来测试以任何语言编写的命令行程序的行为。

查找低级或动态类型程序崩溃的输入特别有用。

为方便起见,我编写了http://hackage.haskell.org/package/proctest,其中包括一些 QuickCheck 与 hspec 和 HUnit 一起使用以通过这种方式测试命令行程序的示例。

于 2012-08-07T20:32:37.280 回答
1

我们使用FsCheck来检查我们的 OCaml 到 F# 的转换是否正确,并且我们的优化版本与未优化版本的工作方式相同。我还计划用它来测试词法分析器和解析器,因为NHol项目使用了解析器组合器。

我们还有帮助函数,允许我们在NUnit(XUnit for .Net)中运行测试。见assertProp

于 2013-09-11T13:40:41.470 回答
0

我使用 QuickCheck 在 LG Linux Mobile 平台上测试 SMS PDU 编码器和解码器。我当时开发的软件的(旧)版本可在http://hackage.haskell.org/package/GenSmsPdu-0.1下载

于 2015-02-02T02:53:16.060 回答
0

这不是我的项目,但该containers包相当广泛地使用 QuickCheck。就个人而言,我尝试用它来比较我写的一个愚蠢的小素筛和一个 in arithmoi,这让我发现了一个 inarithmoi有时会出现段错误。

于 2015-02-02T05:18:40.007 回答