随机值的测试 - 对这种方法的思考?

时间:2008-09-23 18:16:23

标签: unit-testing testing random automated-tests

好的,我一直在研究一个随机图像选择器和队列系统(所以你不会经常看到相同的图像)。

一切都在游泳(就我的蹩脚代码而言)直到我得到了随机位。我想测试它,但你如何测试呢?没有Debug.Assert(i.IsRandom)(遗憾地):D

所以,在用一些茶给它浇水之后我把它的大脑放在上面并提出了以下内容,我只是想知道我是否能想到你的想法?

  • 基本上我知道随机位是问题,所以我把它撕成了一个委托(然后会传递给对象构造函数)。
  • 然后我创建了一个几乎与 live 代码执行相同逻辑的类,但是记住在私有变量中选择的值。
  • 然后我把那个代表扔到了现场课上并对其进行了测试:

Debug.Assert(myObj.RndVal == RndIntTester.ValuePassed);

但是我忍不住想,我是在浪费我的时间吗?我通过大量的迭代来测试它是否随时都会崩溃等等。

你觉得我在浪费时间吗?或者我可以逃脱:

Awesome Random Number Generator

GateKiller's answer让我想起了这个:

Dilbert Random

更新到Clarify

  • 我应该补充一点,我基本上不希望从Y大小的池中看到与X次相同的结果。
  • 添加测试容器基本上可以让我看看是否“随机”选择了以前选择的图像。
  • 我觉得从技术上讲,这里的东西不是在RNG中测试过的(因为我从来没有写过那段代码)但事实是我希望 random 来自有限的池,而我想跟踪它们

19 个答案:

答案 0 :(得分:6)

在维基百科上有一个方便的statistical randomness测试列表和related research。请注意,你肯定不知道某个来源是大多数真正随机的,你只能排除一些可以轻易预测的方式。

答案 1 :(得分:6)

根据要求进行测试:“因此您不会经常看到相同的图像”

要求100张图片。你经常看到一张图片吗?

答案 2 :(得分:5)

如果您有一组固定的项目,并且您不希望它们过于频繁地重复,请随机对该集合进行随机播放。那么你将确保你连续两次看不到相同的图像,感觉你正在收听Top 20收音机等。你会在重复之前完成整个收集。

Item[] foo = …
for (int idx = foo.size(); idx > 1; --idx) {
  /* Pick random number from half-open interval [0, idx) */
  int rnd = random(idx); 
  Item tmp = foo[idx - 1];
  foo[idx - 1] = foo[rnd];
  foo[rnd] = tmp;
}

如果您有太多的项目需要立即收集和随机播放(存储库中数以万计的图像),您可以为同一种方法添加一些分而治之。随机播放图像组,然后对每组进行随机播放。

听起来可能适用于修订后的问题陈述的略有不同的方法是让您的“图像选择器”实现将其最近的选择历史记录保留在最多Y长度的队列中。在返回图像之前,它会测试它是否已经在队列中X次,如果是,它会随机选择另一个图像,直到它找到一个通过。

如果您真的要求测试随机数生成器的质量,我将不得不打开统计书。

答案 3 :(得分:4)

测试一个值是否真正随机是不可能的。你能做的最好的事情就是进行大量的测试并测试你是否得到了合适的分布,但是如果结果是真正随机的,那么即使这样也有(非常小的)失败的可能性。

如果您正在进行白盒测试,并且您知道随机种子,那么您实际上可以计算预期结果,但您可能需要单独测试来测试RNG的随机性。

答案 4 :(得分:2)

  

随机数的生成是   太重要了,不能留下机会。 - Robert R. Coveyou

解决心理问题:

防止明显重复的一个不错的方法是从整套中随机选择几个项目,丢弃重复项。播放那些,然后选择另外几个。多少是“少数”取决于你玩它们的速度和整套的大小,但是例如避免在较大的“20”内重复,而“5分钟”可能没问题。做用户测试 - 作为程序员,你会对幻灯片放映感到厌烦,你不是一个好的测试对象。<​​/ p>

为了测试随机代码,我会说:

步骤1:指定代码必须如何将原始随机数映射到域中的选项,并确保代码正确使用随机数生成器的输出。通过模拟发生器来测试它(或者如果它是PRNG则用已知的测试值接种它)。

步骤2:确保发电机足够随意用于您的目的。如果您使用了库函数,则可以通过阅读文档来完成此操作。如果你自己写的,为什么?

步骤3(仅限高级统计员):对发电机输出的随机性进行一些统计测试。确保你知道测试中错误失败的可能性。

答案 5 :(得分:2)

有些书可以写关于随机性和评估出现的内容是否随机,但我会为你保存数学页面。简而言之,您可以使用chi-square test来确定明显“随机”分布与预期的匹配程度。

如果你正在使用Perl,你可以使用Statistics::ChiSquare模块为你做艰苦的工作。

但是,如果您想确保图片均匀分发,那么您可能不希望它们真正随机。相反,我建议您拍摄整个图像列表,随机播放该列表,然后在需要“随机”图像时从中删除项目。当列表为空时,您重新构建它,重新洗牌并重复。

这种技术意味着给定一组图像,每个单独的图像在列表中每次迭代都不会出现多次。您的图片不禁分布均匀。

一切顺利,

答案 6 :(得分:1)

Random 和类似函数给你的是伪随机数,一系列通过函数产生的数字。通常,您给该函数它的第一个输入参数(也就是“种子”),用于产生第一个“随机”数字。之后,每个最后一个值用作循环的下一次迭代的输入参数。你可以查看关于“伪随机数发生器”的维基百科文章,解释非常好。

所有这些算法都有一些共同之处:该系列经过多次迭代后重复。请记住,这些不是真正的随机数字,只是似乎随机的数字系列。要选择一个发电机而不是另一个发电机,您需要问自己:您想要它做什么?

你如何测试随机性?的确可以。有很多测试。当然,第一个也是最简单的是运行伪随机数生成器很多次,并编译每个结果出现的次数。最后,每个结果应该出现非常接近(迭代次数)/(可能结果的数量)的次数。标准偏差越大,发电机就越差。

第二个是:你当时使用了多少随机数? 2,3?将它们成对(或三联体)并重复上一个实验:经过长时间的迭代后,每个预期结果应该至少出现一次,并且每次结果出现的次数不应该太远预期的。有一些发电机可以正常工作,一次服用一个或两个,但是当你服用3个或更多时(RANDU任何人?)会失败。

还有其他更复杂的测试:有些涉及以对数刻度绘制结果,或者在中间有圆圈的平面上绘制,然后计算有多少绘图落入其中,其他...我相信那些2上面应该足以满足大部分时间(除非你是一个挑剔的数学家)。

答案 7 :(得分:0)

正如其他人所指出的那样,不可能真正测试随机性。您可以(并且应该)将随机性包含在一个特定方法中,然后为每个其他方法编写单元测试。这样,您可以测试所有其他功能,假设您可以从最后一部分中获取随机数。

答案 8 :(得分:0)

嗯,问题是定义的随机数可以重复(因为它们......等待它:随机)。也许你想要做的是保存最新的随机数并将计算出的数字与之比较,如果相等只是计算另一个...但现在你的数字更少随机(我知道不是这样的作为“或多或少”随机性的东西,但让我使用这个时期的术语),因为它们保证不会重复。

无论如何,你永远不应该给出随机数字。 :)

答案 9 :(得分:0)

存储随机值,在使用下一个生成的随机数之前,请检查存储的值。

答案 10 :(得分:0)

任何好的伪随机数生成器都可以让你为生成器播种。如果您使用相同的数字为生成器播种,则生成的随机数流将相同。那么为什么不为随机数生成器播种,然后根据特定的数字流创建单元测试呢?

答案 11 :(得分:0)

我的意见是任何随机的都无法正确测试。

当然你可以尝试对它进行测试,但是有很多组合要尝试你最好只依靠RNG并检查大量的案例。

答案 12 :(得分:0)

随机是随机的。即使相同的图片连续出现4次,它仍然可以被认为是随机的。

答案 13 :(得分:0)

获得一系列非重复随机数:

  1. 创建随机数列表。
  2. 为每个随机数添加序列号
  3. 按照原始随机数
  4. 对排序列表进行排序
  5. 将序列号用作新的随机数。

答案 14 :(得分:0)

不要测试随机性,测试看看你得到的结果是否合适(或者更确切地说,在接受你的结果可能是可取的之前,尝试几次得到不良结果)。 如果您正在测试随机输出,那么就不可能确保您永远不会得到不良结果,但至少可以增加您发现它的可能性。

我要么取N个Y大小的池,检查出现超过X次的任何结果,要么取一个N * Y大小的池,检查每个Y大小的组是否有任何超过X的结果时间(1到Y,2到Y + 1,3到Y + 2等)。 N取决于您希望测试的可靠程度。

答案 15 :(得分:0)

从分布生成随机数。在这种情况下,每个值都应具有相同的出现可能性。如果计算无限量的随机数,则可以获得精确的分布。

实际上,多次调用该功能并检查结果。如果您希望有N个图像,请计算100 * N个randoms,然后计算每个预期数量的数量。大多数应该出现70-130次。使用不同的随机种子重新运行测试以查看结果是否不同。

如果您发现现在使用的发电机不够好,您可以轻松找到一些东西。 Google为“Mersenne Twister” - 这比你需要的更加随意。

为避免图像重新出现,您需要更少随机的内容。一种简单的方法是检查不允许的值,如果是其中之一,则重新计算。

答案 16 :(得分:0)

虽然您无法测试随机性,但您可以测试一系列数字的相关性或分布。

难以测试目标:每当我们需要图像时,随机选择4张图像中的一张。

易于测试目标:对于我们选择的每100张图像,4张图像中的每张图片必须至少出现20次。

答案 17 :(得分:0)

我同意亚当罗森菲尔德的观点。对于你所谈论的情况,唯一可以测试的是整个范围内的分布。

我经常遇到的情况是我用我最喜欢的语言的PRNG生成伪随机数,然后将它们操作到所需的范围。为了检查我的操作是否影响了分布,我生成一堆数字,操纵它们,然后检查结果的分布。

为了获得一个好的测试,你应该产生比你的范围多至少几个数量级的数字。您使用的值越多,测试就越好。显然,如果你有一个非常大的范围,这将无法工作,因为你将不得不生成太多的数字。但在你的情况下,它应该工作正常。

以下是Perl中的一个示例,说明了我的意思:

for (my $i=0; $i<=100000; $i++) {
   my $r = rand;        # Get the random number
   $r = int($r * 1000); # Move it into the desired range
   $dist{$r} ++;        # Count the occurrences of each number
}

print "Min occurrences: ", (sort { $a <=> $b } values %dist)[1], "\n";
print "Max occurrences: ", (sort { $b <=> $a } values %dist)[1], "\n";

如果最小和最大事件之间的差异很小,那么您的分布是好的。如果它很宽,那么你的发行可能不好。您也可以使用此方法检查您的范围是否被覆盖以及是否遗漏了任何值。

同样,您生成的数字越多,结果就越有效。我倾向于从小做起,并在合理的时间内处理我的机器将处理的任何事情,例如五分钟。

答案 18 :(得分:0)

假设您正在测试整数内的随机性范围,验证这一点的一种方法是创建一个gajillion(好,可能是10,000左右)'随机'数字并在直方图上绘制它们的出现。

          ******    ******           ****
***********************************************
*************************************************
*************************************************
*************************************************
*************************************************
*************************************************
*************************************************
*************************************************
*************************************************
         1         2         3         4         5
12345678901234567890123456789012345678901234567890

以上显示了“相对”的正态分布。

如果它看起来更偏斜,例如:

          ******    ******           ****
    ************  ************  ************
    ************  ************  ***************
    ************  ************  ****************
    ************  ************  *****************
    ************  ************  *****************
   ***************************  ******************
   **************************** ******************
******************************* ******************
**************************************************
         1         2         3         4         5
12345678901234567890123456789012345678901234567890

然后你可以看到随机性较低。正如其他人所提到的那样,也存在重复的问题。

如果您要使用生成器生成10,000个随机数的二进制文件,比如从1到1024的随机数,并尝试使用压缩(zip,gzip等)压缩该文件,那么您可以比较两个文件大小。如果有很多压缩,那么它并不是特别随机。如果尺寸没有太大变化,那么它“非常随机”。

为什么会这样?

压缩算法寻找模式(重复和其他方式)并以某种方式减少它。查看这些压缩算法的一种方法是衡量文件中的信息量。高度压缩的文件具有很少的信息(例如随机性),而小压缩的文件具有很多信息(随机性)