Ruby:在代码中使用rand()但编写测试以验证概率 [英] Ruby: Using rand() in code but writing tests to verify probabilities

查看:75
本文介绍了Ruby:在代码中使用rand()但编写测试以验证概率的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些代码可以根据加权随机数传送内容.重量更大的东西更有可能被随机选择.现在,作为一名优秀的红宝石专家,我想用测试覆盖所有这些代码.而且我想测试事物是否已根据正确的概率获取了.

I have some code which delivers things based on weighted random. Things with more weight are more likely to be randomly chosen. Now being a good rubyist I of couse want to cover all this code with tests. And I want to test that things are getting fetched according the correct probabilities.

那我该如何测试呢?为应该是随机的东西创建测试将使比较实际值与预期值非常困难.我有一些想法,以及为什么它们行不通:

So how do I test this? Creating tests for something that should be random make it very hard to compare actual vs expected. A few ideas I have, and why they wont work great:

  • 在我的测试中对Kernel.rand进行存根以返回固定值.这很酷,但是rand()被多次调用,我不确定我是否可以使用足够的控件来绑定它来测试我需要的内容.

  • Stub Kernel.rand in my tests to return fixed values. This is cool, but rand() gets called multiple times and I'm not sure I can rig this with enough control to test what I need to.

获取大量随机项,然后比较实际比率与预期比率.但是除非我可以无限次运行它,否则它将永远不会是完美的,并且如果我在RNG中遇到不幸的话,可能会间歇性地失败.

Fetch a random item a HUGE number of times and compare the actual ratio vs the expected ratio. But unless I can run it an infinite number of times, this will never be perfect and could intermittently fail if I get some bad luck in the RNG.

使用一致的随机种子.这使得RNG可以重复,但是仍然没有提供任何证据证明项目A将在80%的时间发生(例如).

Use a consistent random seed. This makes the RNG repeatable but it still doesn't give me any verification that item A will happen 80% of the time (for example).

那我可以使用哪种方法为随机概率编写测试覆盖率?

So what kind of approach can I use to write test coverage for random probabilities?

推荐答案

我认为您应该分开目标.正如您提到的,其中之一是对Kernel.rand进行存根.例如,使用rspec,您可以执行以下操作:

I think you should separate your goals. One is to stub Kernel.rand as you mention. With rspec for example, you can do something like this:

test_values = [1, 2, 3]
Kernel.stub!(:rand).and_return( *test_values )

请注意,除非您使用内核作为接收者来调用rand,否则该存根将不起作用.如果仅调用"rand",则当前的"self"将收到该消息,并且实际上将获得一个随机数而不是test_values.

Note that this stub won't work unless you call rand with Kernel as the receiver. If you just call "rand" then the current "self" will receive the message, and you'll actually get a random number instead of the test_values.

第二个目标是做一些像现场测试这样的事情,在这里您实际上会生成随机数.然后,您将使用某种容忍度来确保您接近所需的百分比.但是,这永远不会是完美的,并且可能需要人工来评估结果.但是这样做仍然很有用,因为您可能意识到另一个随机数生成器可能更好,例如从/dev/random中读取.另外,进行这种测试也是很好的,因为假设您决定迁移到一种新的平台,该平台的系统库不擅长生成随机性,或者某个版本中存在某些错误.该测试可能是一个警告信号.

The second goal is to do something like a field test where you actually generate random numbers. You'd then use some kind of tolerance to ensure you get close to the desired percentage. This is never going to be perfect though, and will probably need a human to evaluate the results. But it still is useful to do because you might realize that another random number generator might be better, like reading from /dev/random. Also, it's good to have this kind of test because let's say you decide to migrate to a new kind of platform whose system libraries aren't as good at generating randomness, or there's some bug in a certain version. The test could be a warning sign.

这实际上取决于您的目标.您只想测试加权算法还是随机性?

It really depends on your goals. Do you only want to test your weighting algorithm, or also the randomness?

这篇关于Ruby:在代码中使用rand()但编写测试以验证概率的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆