如何保证 FsCheck 的重现性

Dan*_*ian 5 f# nunit unit-testing fscheck

我们希望在持续集成中使用 FsCheck 作为单元测试的一部分。因此,确定性和可重复的行为对我们来说非常重要。

FsCheck 是一个随机测试框架,可以生成有时可能会中断的测试用例。关键是,我们不仅使用必须为每个输入保留的属性,例如 say List.rev >> List.rev === id。相反,我们做一些数字,一些测试用例可能会因为条件不好而导致测试中断。

问题是:我们如何保证,一旦测试成功,它就永远成功?

到目前为止,我看到以下选项:

  • 对种子进行硬编码,例如 0。这将是最简单的解决方案。
  • 制作非常具体的自定义生成器,避免坏例子。当然可能,但结果可能会非常困难,尤其是在要生成许多对象的情况下。
  • 接受它,在某些情况下,由于病理情况,构建可能是红色的,只需重新运行即可。

在这种设置中使用 FsCheck 的惯用方法是什么?

Kur*_*out 2

(我开始写评论,但它太长了,我想它应该有自己的答案)。

使用 FsCheck 测试并不适用于每个输入的属性是很常见的。例如,List.rev如果您运行list<float>.

数值稳定性本身就是一个棘手的问题 - FsCheck 中没有任何非确定性可以归咎于这里(FsCheck 是完全确定性的,它只是一个输入生成器......)。您所指的“非确定性”可能是某些处理器中的浮点运算中的错误等。但即使在这种情况下,你不想了解它们吗?如果您的算法对于一类输入来说在数值上不稳定,您不想了解一下吗?如果你不这样做,在我看来,你正在为自己的生产中的一些真正的非确定性做好准备。

编写不适用于 FsCheck 中给定类型的所有输入的属性的惯用方法是编写生成器和收缩器。您可以将==>其作为一个步骤,但它不能很好地扩展到复杂的先决条件。你说这可能会变得相当困难 - 从某种意义上说这是真的,我保证你会学到一些关于你的代码的东西。一件好事!

修复种子是一个坏主意,除非重现以前发现的错误。我的意思是,在实践中你会做什么:继续重新运行测试直到通过,然后修复种子并声明“工作完成”?