我的网域涉及一个随机确定的选择,我不确定如何对其进行单元测试。
作为一个简单的例子,假设我想确保myobject.makeChoice()
在75%的时间内返回true
并在{25}的时间内false
返回myobject.getChoiceAPercent()
。我怎么能对它进行单元测试呢?
我可以断言myobject.makeChoice()
是75,但那样
似乎微不足道,没有用,并且不满意,因为它没有测试实际结果。
我可以运行true
1,000次并断言它
返回makeChoice()
70%到80%的时间,或一些统计
这样的方法,但那似乎脆弱,缓慢,和
不令人满意的。
我可以使用预定的随机生成器运行单元测试
随机种子并断言[true, true, false, true, true]
运行5次返回
例如public boolean makeChoice() {
return this.random.nextDouble() < 0.75;
}
,但似乎是
与断言随机(123)== 456一样,也似乎不能令人满意,因为我不会测试我感兴趣的实际域名。
似乎可以通过随机发生器本身的归纳推理证明随机选择是正确的,而不是单元测试。因此,随机生成的内容不适合自动化测试,还是有一种我不知道的简单方法?
[edit] 为了避免对“真随机”与“伪随机”等的争议,让我们假设以下实现:
makeChoice
如何约75%的时间对true
返回{{1}}进行单元测试?
答案 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
方案,可能就好了。