注意:我提到接下来几段作为背景。如果你只是想要一个TL; DR,可以跳到编号的问题,因为它们只与这些信息间接相关。
我正在编写一个python脚本,用POSIX日期(以及其他东西)做一些事情。单元测试这些看起来有点困难,因为可以遇到的日期和时间范围很广。
当然,尝试测试每一个可能的日期/时间组合是不切实际的,所以我想我会尝试一个随机化输入的单元测试,然后报告测试失败时的输入。从统计学的角度来说,我认为如果我试图考虑所有潜在的问题区域(由于缺少的东西)或测试所有情况(由于纯粹的不可行性),我可以实现更多的测试完整性,假设我运行它足够的时间。
所以这里有几个问题(主要与上述内容间接相关):
答案 0 :(得分:12)
我同意费德里科 - 随机测试适得其反。如果测试不能可靠地通过或失败,则很难修复并知道它是固定的。 (当你引入不可靠的依赖时,这也是一个问题。)
但是,相反,您可能希望确保以其他方式获得良好的数据覆盖率。例如:简而言之,仍然尝试很多值,但是以编程方式和可重复的方式执行。你不需要在测试中尝试成为文字的每个值 - 循环测试一个轴的所有已知值,等等。
你永远不会得到完整的覆盖范围,但它至少是可重复的。
编辑:我确定是随机测试有用的地方,尽管可能不适用于单元测试。但是,在这种情况下,我想提出一些建议:使用一个RNG创建一个随机但已知的种子,然后使用该值播种新的RNG - 并记录它。这样一来,如果发生了一些有趣的事情,你将能够通过启动带有记录种子的RNG来重现它。
答案 1 :(得分:6)
关于第3个问题,在我看来,随机测试不非常适合单元测试。如果应用于同一段代码,则单元测试应始终成功,或者始终失败(即,由于错误导致的错误行为应该是可重现的)。但是,您可以使用随机技术生成大型数据集,然后在单元测试中使用该数据集;这没什么不对。
答案 2 :(得分:3)
答案 3 :(得分:1)
Q1)我发现具有大量并发性的分布式系统是随机测试的理想选择。很难为这些应用程序创建所有可能的场景,但随机测试可能会暴露您从未想过的问题。
Q2)我猜你可以尝试使用统计数据来建立一个发现所有“错误”的置信区间。但实际的答案是:尽可能多地进行随机测试。
Q3)我发现随机测试很有用,但在之后你已经编写了正常的单位,积分和回归测试电池。您应该将随机测试作为正常测试套件的一部分进行集成,尽管可能只是一小部分。如果没有别的,你可以避免测试本身的位腐烂,并在团队使用不同的随机输入运行测试时获得一些小的覆盖。
Q4)编写随机测试时,请确保使用测试结果保存随机种子。没有什么比发现你的随机测试捕获到一个错误,并且无法使用相同的输入再次运行测试更令人沮丧。确保您的测试也可以使用保存的种子执行。
答案 4 :(得分:1)
一些事情:
另请注意:重复性在测试中非常重要!因此,让您的测试工具记录它使用的随机种子,并让参数以相同的种子开头。此外,让它从一个已知的“基本状态”开始(即,从服务器上的图像重新安装所有内容并从那里开始)或一些可恢复的基本状态( ie ,从该图像重新安装,然后根据测试工具作为参数的一些随机种子对其进行更改。)
当然,如果该工具具有诸如“保存状态每20,000个事件”和“在事件#之前停止”和“向前迈步1/10/100事件”这样的工具,开发人员将会很感激。这将极大地帮助他们重现问题,找到并修复它。
正如其他人所指出的,服务器是另一个暴露给用户的东西。获取1,000,000个URL的列表(来自服务器日志的grep),然后将它们提供给随机数生成器。
请记住:“系统24小时随机冲击没有错误”并不意味着它已经准备好发货,它只是意味着它足够稳定以开始一些严肃的测试。在它可以做到这一点之前,QA应该随意说“看,你的POS甚至不能在生命中随机用户模拟24小时 - 你解决了这个问题,我将花一些时间编写更好的工具。”
哦,是的,最后一件事:除了“尽可能快地和尽可能地坚硬”测试之外,还有能力做到“真正的用户[可能是一个疯狂的人,或者是一个婴儿束缚了键盘/鼠标]会的。“也就是说,如果你正在进行随机的用户事件;以非常快的打字员或非常快的鼠标用户可以做的速度(偶尔延迟,模拟一个慢人),以及“我的程序可以快速吐出事件”的速度来做它们。这些是两种非常不同的*类型的测试,当发现错误时会产生非常不同的反应。
答案 5 :(得分:1)
要使测试可重现,只需使用固定的种子起始值即可。这确保了测试运行时使用相同的数据。测试将可靠地通过或失败。
答案 6 :(得分:0)
这可能稍微偏离主题,但如果您使用.net,则有Pex,它执行与随机测试类似的操作,但通过尝试生成“随机”测试用例更直观通过代码练习所有路径。
答案 7 :(得分:0)
以下是我对类似问题的回答:Is it a bad practice to randomly-generate test data?。其他答案也可能有用。
随机测试是一种不好的做法 只要你没有解决方案 oracle问题,即 确定哪个是预期的 鉴于它的软件结果 输入
如果你解决了oracle问题,那么 可以比简单更进一步 随机输入生成。您可以 选择输入分布 你的软件的特定部分得到 比简单运用更多 随机的。
然后从随机测试切换到 统计检验。
if (a > 0) // Do Foo else (if b < 0) // Do Bar else // Do Foobar
如果您随机选择
a
和b
int
范围,你行使Foo
50% 时间,Bar
25%的时间和Foobar
25%的时间。这有可能 您将在Foo
中找到更多错误 而不是Bar
或Foobar
。如果您选择
a
,那就是 负66.66%的时间,Bar
和Foobar
得到的锻炼比锻炼更多 你的第一次发行。的确如此 每个分支都有三个分支 33.33%的时间。当然,如果您观察到的结果是 与预期结果不同, 你必须记录所有可能的东西 有用的重现错误。
答案 8 :(得分:0)
随机测试具有巨大的优势,可以以极低的成本生成单个测试。即使您只有部分oracle(例如,软件崩溃了吗?)
,情况也是如此在复杂系统中,随机测试会发现很难通过任何其他方式找到的错误。想想这对安全测试意味着什么:即使你不进行随机测试,黑帽子也会,你会发现你错过的错误。
随机测试的一个迷人的子领域是随机差分测试,其中两个或多个应该显示相同行为的系统用共同输入激励。如果他们的行为不同,则会发现一个错误(在一个或两个中)。这已经被应用于编译器的测试,并且总是发现任何编译器中以前没有遇到过该技术的错误。即使您只有一个编译器,您也可以在不同的优化设置上尝试查找不同的结果,当然崩溃总是意味着错误。