Unit testing 单元测试中的随机数据?

Unit testing 单元测试中的随机数据?,unit-testing,tdd,mocking,Unit Testing,Tdd,Mocking,我有一个同事,他为用随机数据填充字段的对象编写单元测试。他的理由是,它提供了更广泛的测试范围,因为它将测试许多不同的值,而正常测试只使用一个静态值 我给了他很多反对的理由,主要有: 随机值意味着测试不是真正可重复的(这也意味着如果测试可以随机失败,它可以在构建服务器上这样做并破坏构建) 如果它是一个随机值,而测试失败,我们需要a)修复对象,b)强迫自己每次测试该值,因此我们知道它是有效的,但由于它是随机的,我们不知道该值是什么 另一位同事补充道: 如果我正在测试一个异常,随机值将无法确保测

我有一个同事,他为用随机数据填充字段的对象编写单元测试。他的理由是,它提供了更广泛的测试范围,因为它将测试许多不同的值,而正常测试只使用一个静态值

我给了他很多反对的理由,主要有:


  • 随机值意味着测试不是真正可重复的(这也意味着如果测试可以随机失败,它可以在构建服务器上这样做并破坏构建)
  • 如果它是一个随机值,而测试失败,我们需要a)修复对象,b)强迫自己每次测试该值,因此我们知道它是有效的,但由于它是随机的,我们不知道该值是什么
另一位同事补充道:

  • 如果我正在测试一个异常,随机值将无法确保测试最终处于预期状态
  • 随机数据用于冲洗系统和负载测试,而不是用于单元测试
还有谁能补充我能给他的理由让他停止这样做


(或者,这是一种可以接受的编写单元测试的方法,而我和我的其他同事错了吗?

根据您的对象/应用程序,随机数据将在负载测试中占有一席之地。我认为更重要的是使用明确测试数据边界条件的数据。

能否生成一些随机数据一次(我的意思是只生成一次,而不是每次测试运行一次),然后在此后的所有测试中使用它

我可以肯定地看到创建随机数据来测试那些您没有想到的情况的价值,但是您是对的,拥有可以随机通过或失败的单元测试是一件坏事

  • 如果它是一个随机值,而测试失败,我们需要a)修复对象,b)强迫自己每次测试该值,因此我们知道它是有效的,但由于它是随机的,我们不知道该值是什么

如果您的测试用例没有准确地记录它正在测试的内容,那么您可能需要重新编码测试用例。我总是希望有一些日志,我可以在测试用例中引用,这样我就可以确切地知道是什么原因导致它失败,无论是使用静态数据还是随机数据。

这里有一个中途之家,它有一些用处,那就是在PRNG中植入一个常量。这允许您生成可重复的“随机”数据

就个人而言,我确实认为有些地方(恒定的)随机数据在测试中是有用的——在你认为你已经完成了所有仔细思考过的角落之后,使用PRNG的刺激有时可以找到其他东西。

在书中,有一章叫做“美丽的测试”,在这一章中,他介绍了算法的测试策略。其中一段被称为“随机测试行为”,他在其中创建随机数组以彻底测试算法。你可以在谷歌图书在线阅读其中的一些内容,但这是一本值得拥有的好书


所以基本上这只是表明生成随机数据进行测试是一个可行的选择

有一个折衷方案。你的同事确实在做什么,但我认为他做错了。我不确定完全随机测试是否有用,但它肯定不是无效的

程序(或单元)规范是一种假设,即存在满足它的某个程序。程序本身就是这一假设的证据。单元测试应该是试图提供反证来反驳程序是按照规范工作的

现在,您可以手工编写单元测试,但这实际上是一项机械任务。它可以自动化。你所要做的就是编写规范,机器可以生成大量的单元测试,试图破坏你的代码

我不知道您使用的是什么语言,但请参见此处:

爪哇

Scala(或Java)

哈斯克尔

.NET:

这些工具将把您格式良好的规范作为输入,并自动生成任意数量的单元测试,以及自动生成的数据。他们使用“收缩”策略(你可以调整)来找到最简单的测试用例来破坏你的代码,并确保它很好地覆盖了边缘用例


快乐测试

当你的人无法查看他是否已修复测试时,他如何再次运行该测试?即,他失去了测试的可重复性

虽然我认为在测试中抛出大量随机数据可能有一定的价值,但正如在其他回复中提到的,它更多地属于负载测试的范畴。这几乎是一种“希望检验”的做法。我认为,在现实中,你的家伙根本没有考虑他试图测试的东西,并希望随机性最终会捕获一些神秘的错误,以此弥补这种想法的不足


因此,我将用他的论点是,他是懒惰的。或者,换一种说法,如果他没有花时间去理解他试图测试的东西,这可能表明他没有真正理解他正在编写的代码。

我们今天遇到了这个问题。我想要伪随机的(因此就大小而言,它看起来像压缩的音频数据)。我要做的是,我还想要确定性。rand()在OSX上与在Linux上不同。除非我重新播种,否则它随时都可能改变。因此,我们将其改为确定性,但仍然是伪随机的:测试是可重复的,就像使用屏蔽数据一样(但编写起来更方便)

这是而不是通过一些随机暴力通过代码路径进行测试。这就是区别:仍然是确定性的,仍然是可重复的,仍然使用看起来像真实输入的数据对复杂逻辑中的边缘情况运行一组有趣的检查。仍然是单元测试


这仍然是随机的吗?让我们边喝啤酒边谈。:-)

这种测试称为测试。如果做得好,它可以从真正黑暗的角落里熏出虫子

解决您对再现性的担忧:正确的ap方法