我该如何测试随机选择?

时间:2012-01-06 01:34:57

标签: unit-testing random

我的网域涉及一个随机确定的选择,我不确定如何对其进行单元测试。

作为一个简单的例子,假设我想确保myobject.makeChoice()在75%的时间内返回true并在{25}的时间内false返回myobject.getChoiceAPercent()。我怎么能对它进行单元测试呢?

  1. 我可以断言myobject.makeChoice()是75,但那样 似乎微不足道,没有用,并且不满意,因为它没有测试实际结果。

  2. 我可以运行true 1,000次并断言它 返回makeChoice() 70%到80%的时间,或一些统计 这样的方法,但那似乎脆弱,缓慢,和 不令人满意的。

  3. 我可以使用预定的随机生成器运行单元测试 随机种子并断言[true, true, false, true, true]运行5次返回 例如public boolean makeChoice() { return this.random.nextDouble() < 0.75; } ,但似乎是 与断言随机(123)== 456一样,也似乎不能令人满意,因为我不会测试我感兴趣的实际域名。

  4. 似乎可以通过随机发生器本身的归纳推理证明随机选择是正确的,而不是单元测试。因此,随机生成的内容不适合自动化测试,还是有一种我不知道的简单方法?

    [edit] 为了避免对“真随机”与“伪随机”等的争议,让我们假设以下实现:

    makeChoice

    如何约75%的时间对true返回{{1}}进行单元测试?

5 个答案:

答案 0 :(得分:0)

随机性测试似乎并不是随机的。但是为了测试唯一性/冲突,我通常使用哈希结构并将随机值作为键插入。重复的密钥被覆盖。通过计算唯一键的最终数量与迭代总数,您可以“测试”算法的唯一性。

答案 1 :(得分:0)

您写的代码与RNG没有分离。也许你可以这样写:

public boolean makeChoice(double randnum) {
  return randnum < 0.75;
}

然后测试关键值以测试实现。

或者你可以将随机对象初始化为一个特定的种子,它会在[0,1]之间给出已知的随机数,并根据你对这些已知数字的预期进行测试。

或者你可以定义一个IRandom,为Random编写一个实现接口的前端并在程序中使用它。然后你可以用模拟IRandom测试它,按顺序给出数字0.00,0.01,0.02 ......,0.99,1.00并计算成功次数。

答案 2 :(得分:0)

不要测试代码的随机性,通过传入或从随机数存储中获取值来测试随机性的结果。

获得100%的单元测试覆盖率是一个很好的目标,但这是收益递减规律。你写过PRNG了吗?

编辑:同时查看此答案,因为它有几个很好的链接:How do you test that something is random? Or "random enough'?

答案 3 :(得分:0)

我的第二个“脱钩”策略。我认为任何取决于随机值或时间的东西,应该只是将它确定为“另一个依赖”的“又一个输入”。然后你注入一个你要写或信任的时钟或RNG。

例如,在你的情况下,如果“选择”在80%的时间而不是75%的时间都是真的,你的对象真的会表现得不同吗?我怀疑你的代码中有很大一部分只关心选择是真是假,还有另外一种选择。

这就打开了如何测试随机生成器的问题,在这种情况下,我认为依赖于“大数”规则,一些近似,数学和简单信任rand()是更好的方法。

答案 4 :(得分:0)

因为它是一个随机布尔值,编写2个测试(一个用于TRUE,一个用于FALSE)可能就足够了如果行为不依赖于过去的“随机” “结果(至少对我来说,不清楚这个问题)。

换句话说:如果连续结果不相互依赖,您可以测试单个TRUE方案,单个FALSE方案,可能就好了。