测试具有随机行为的程序的最佳实践是什么?


14

在进行研发工作时,我经常发现自己编写的程序在行为上有很大的随机性。例如,当我从事基因编程工作时,我经常编写生成并执行任意随机源代码的程序。

测试此类代码的问题在于,错误通常是间歇性的,并且很难重现。这不仅仅是将随机种子设置为相同的值并重新开始执行。

例如,代码可能从内核环形缓冲区读取一条消息,然后对消息内容进行条件跳转。自然,当以后尝试重现该问题时,环形缓冲区的状态将已更改。

即使此行为是一种功能,它也可能以意想不到的方式触发其他代码,从而经常揭示出单元测试(或人工测试人员)找不到的错误。

是否有建立此类测试系统的最佳实践?如果是这样,一些参考资料将非常有帮助。如果没有,欢迎任何其他建议!


5
你也不能嘲笑内核环形缓冲区吗?您的代码还有其他随机方面吗?
乔纳森·梅勒

1
@JonathanMerlet潜在地,但是问题是,在部署时,代码将可以访问真实的环形缓冲区(实际上是真实的OS)。因此,如果仅在模拟版本上进行测试,则将发现这些错误的时间推迟到以后。
约翰·杜塞特

在我看来,这个问题与程序的随机行为无关(因为它可以由随机种子控制),而是与“内核环形缓冲区”的特定状态有关。因此,您的问题实际上是“如何测试依赖外部状态的程序”,对吗?
AakashM

@AakashM,是的,这是表达它的更好方法。更具体地说,是具有外部状态的程序,该程序随机访问或更改外部状态。
约翰·杜塞特

Answers:


7

如建议的那样添加钩子以重新创建精确的状态非常有用。还要对系统进行检测,以便它可以转储其“种子”(在您的情况下,包括PRNG种子以及内核环形缓冲区以及任何其他不确定性输入源)。

然后使用真正的随机输入运行测试,并使用以前发现的有趣案例进行回归式测试。

在您访问内核的特定情况下,无论如何我建议您进行模拟。使用模拟来强制在实践中不太可能出现的对等类,本着容器的“空”和“满”的精神,或为容器“ 0、1、2 ^ n,2 ^ n + 1,许多”可数的东西。然后,您就可以使用模拟和真实的东西进行测试,知道您已经处理并测试了到目前为止已经想到的案例。

基本上,我建议的内容是确定性和非确定性输入的混合,确定性输入是您可以想到的和您感到惊讶的输入的混合。


6

要做的一件合理的事情是为测试生成一个具有恒定值的随机数生成器,以使您获得确定的行为。


1
这个; 或完全模拟出prng
jk。

1
谢谢你的建议!我已经进行了单元测试,但是我无法手动测试所有可能的程序。
约翰·杜塞特

2
但这意味着您无法测试随机性是否正常工作。–
路易·里斯

2

我认为统计测试是唯一的方法。就像通过统计测试“测试”随机数的随机性一样,因此也需要使用随机行为的算法。

只需使用相同或不同的输入多次运行算法,然后将其相互比较即可。这种方法的问题是完成测试所需的计算时间大量增加。


不一定,因为您可以选择一组小的“跨度”输入并在它们上运行多次-确定可靠性所需的输入数量可能会更少。这种“跨越”集应输入代码的每一个分支,初始化所有对象,等等
丹尼尔Moskovich的

2

我不是该领域的专家,但是相对于随机程序测试,这是一门科学的论文。

如#Euphoric所述,如果您无法轻松创建测试类,则可以使用统计测试。Borning等。比较传统方法和统计方法。@Euphoric建议的统计测试的一般化可能是Whittaker讨论的一种。他建议创建所需行为(在您的情况下是随机的)的随机模型,然后从该模型生成特定的测试用例(请参阅他的专用论文)。


谢谢!看起来非常有帮助。对于外部学术机构,可以从作者的Google代码库中提取论文的预印本:team4model.googlecode.com/svn/trunk/resources/paper/…–
John Doucette
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.