Ruby:在代码中使用rand()但编写测试来验证概率

Ale*_*yne 7 ruby random statistics unit-testing probability

我有一些代码可以根据加权随机来提供东西.重量更重的东西更有可能随机选择.现在我是一个很好的rubyist,我想用测试来覆盖所有这些代码.而且我想测试根据正确的概率获取的东西.

那么我该如何测试呢?为随机的东西创建测试会使实际与预期的比较变得非常困难.我有一些想法,以及为什么它们不能很好地工作:

  • Stub Kernel.rand在我的测试中返回固定值.这很酷,但rand()被多次调用,我不确定我是否可以通过足够的控制来测试它以测试我需要的东西.

  • 取一个随机项很多次,并比较实际比率与预期比率.但除非我可以无数次运行,否则这将永远不会是完美的,如果我在RNG中运气不好,可能会间歇性地失败.

  • 使用一致的随机种子.这使得RNG可重复,但它仍然没有给我任何验证项目A将在80%的时间内发生(例如).

那么我可以使用什么样的方法来编写随机概率的测试覆盖率?

Kel*_*vin 9

我认为你应该分开你的目标.一个是你提到的存根Kernel.rand.以rspec为例,你可以这样做:

test_values = [1, 2, 3]
Kernel.stub!(:rand).and_return( *test_values )
Run Code Online (Sandbox Code Playgroud)

请注意,除非您使用Kernel作为接收器调用rand,否则此存根将不起作用.如果你只是调用"rand",那么当前的"self"将收到消息,你实际上会得到一个随机数而不是test_values.

第二个目标是执行类似于实际生成随机数的字段测试.然后,您可以使用某种公差来确保接近所需的百分比.这永远不会是完美的,并且可能需要人来评估结果.但它仍然有用,因为您可能会意识到另一个随机数生成器可能更好,例如从/ dev/random读取.此外,进行这种测试是很好的,因为假设您决定迁移到一种新的平台,其系统库不如生成随机性,或者某个版本中存在某些错误.测试可能是一个警告标志.

这真的取决于你的目标.你只想测试你的加权算法,还是随机性?


Don*_*oby 8

最好是将Kernel.rand存根以返回固定值.

Kernel.rand不是你的代码.您应该假设它有效,而不是尝试编写测试它而不是代码的测试.使用您选择并明确编码的固定值集合比添加对特定种子生成的rand的依赖性更好.