怎样知道它是不是随机数?如何测试一个随机数生成器

有些程序很容易测试,但并非所有程序都是如此。自动化测试的目的是以现在的时间成本,来换取未来的时间成本。很多程序员们经常自己写一个小玩意,就不爱写测试了,这是因为他们觉得这个小玩意也就用那么几次,不值得为它单写一个测试。从这个角度上看,这是没错的。大型项目经常会有比较完备的测试,因为这个项目可能会交付很长时间,也可能会有很长的维护时间。这时候测试的成本就可以在未来得到回报。测试随机数生成器,首先要回答的问题是:值不值得做这个测试?如果说这个随机数生成器本来就是系统提供的接口,那是否我们有必要费精力去测试它呢?如果它是不可靠的,那可能暗示着你的技术选型出了问题。如果它可靠(伪随机数也算是可靠),那是否可以使用系统的随机数生成器来生成你自己特定的随机数生成器呢?在这种情况下,自己写的随机数生成器还是可能需要测试的。那应该怎么测试它呢?

让我们来举个简单的例子。比如我们需要得到由两位数字组成的随机字符串(”00”~”99”),它要做的仅仅是调用系统接口生成0~99的数字并格式化为”00”~”99”的字符串。这时我们只需测试它调用系统接口的参数,以及格式化的逻辑即可。而它们都可以通过mock等技术手段很容易地测试。在系统提供的随机数生成器的支持下,应该是可以满足大部分的随机需求的。

如果你非要以打硬仗的方式来测试随机数的话,除去成本因素,要想从纯技术上回答这个问题,那就要先回答另一个问题:什么是随机数?这就回到了业务的本质:在不考虑测试时,在什么情况下你会认为它是一个随机数?简单起见,我们就以0~99的伪随机数为例。取决于业务,可能你的需求是:①连续两次执行结果基本不同(“基本”是由于真随机的不可预测性,它们是可能相同的),或者是②连续执行100遍每次数字都不同,或者是③计算一万遍,要求结果呈现怎样怎样的分布。对于①来说,两次计算结果相同的概率只有百分之一(1% 1% 100),三次结果相同的概率只有万分之一(1% 1% 1% * 100)。所以测试可以这样来设计:调用两次,如果结果相同,那就再调用一次,如果还相同,那就再调用,直至不同为止。最后看调用次数count:如果count = 2,很好。如果count = 3,那就说明现在正好是1%的那次。如果count = 4,说明是0.01%的那次。理想情况下,如果每天运行100次测试,可能会有1次count = 3,运行100天,有1次count = 4,运行10000天(大约27年),会有一次count = 5。根据业务的容忍程度判断count的大小,例如当它大于5就算测试失败。虽然偶尔也会出现count = 6的情况,但是非常罕有,平均2700年会有一次,而且就算测试失败,也很容易排查到这个问题。所以就可以认为是符合业务需求。对于②来说,那就执行100遍看结果好了,也是技术上可实现的。对于③来说,其实与①有相似之处,只要能够描述出来,就能够测试出来。只要自己控制好测试的阈值就可以了。

维基百科上提供了一些随机性测试方法。只要能描述,就可以测试。但是,值得吗?