Unit testing 我应该如何测试随机选择?

Unit testing 我应该如何测试随机选择?,unit-testing,random,Unit Testing,Random,我的领域涉及一个随机确定的选择,我不确定如何对其进行单元测试 举个简单的例子,假设我想确保myobject.makeChoice()在75%的时间内返回truefalse25%的时间。我如何进行单元测试 我可以断言myobject.getChoiceAPercent()是75,但是 因为它没有测试实际的结果,所以看起来很琐碎,没有用处,也不令人满意 我可以运行myobject.makeChoice()1000次并断言它 返回true70%到80%的时间或某些统计数据 方法是这样的,但那似乎是脆弱

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

举个简单的例子,假设我想确保
myobject.makeChoice()
在75%的时间内返回
true
false25%的时间。我如何进行单元测试

  • 我可以断言
    myobject.getChoiceAPercent()
    是75,但是 因为它没有测试实际的结果,所以看起来很琐碎,没有用处,也不令人满意

  • 我可以运行
    myobject.makeChoice()
    1000次并断言它 返回
    true
    70%到80%的时间或某些统计数据 方法是这样的,但那似乎是脆弱的,缓慢的,和 不令人满意

  • 我可以使用预先确定的随机生成器或 随机种子并断言
    makeChoice()
    运行5次返回
    [true,true,false,true,true]
    ,例如,但这似乎是 与断言random(123)==456相同,而且似乎不令人满意,因为我不会测试我感兴趣的实际域

  • 似乎随机选择可以通过随机发生器本身的归纳推理而不是单元测试来证明是正确的。那么,随机生成的内容是否不适合自动测试,或者是否有一种我不知道的简单方法

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

    public boolean makeChoice() {
      return this.random.nextDouble() < 0.75;
    }
    
    public boolean makeChoice(){
    返回此.random.nextDouble()<0.75;
    }
    

    如何对
    makeChoice
    大约75%的时间返回
    true
    进行单元测试?

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

    您编写的代码没有与RNG解耦。也许你可以这样写:

    public boolean makeChoice(double randnum) {
      return randnum < 0.75;
    }
    
    public boolean makeChoice(双随机数){
    返回randnum<0.75;
    }
    
    然后测试键值以测试实现

    或者,您可以将随机对象初始化为特定的种子,该种子给出[0,1]之间的已知随机数,并根据这些已知数的预期结果进行测试


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

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

    获得100%的单元测试覆盖率是一个不错的目标,但这是收益递减定律。你写了PRNG吗

    编辑:也可以看看这个答案,因为它有几个很好的链接:

    我支持“脱钩”策略。我喜欢认为任何依赖于随机值或时间的东西,都应该果断地将其视为“又一个依赖项”的“又一个输入”.然后你注入一个时钟,或一个你将要写入或信任的RNG

    例如,在您的例子中,如果“选择”在80%的时间里是正确的,而不是在75%的时间里是正确的,那么您的对象真的会有不同的行为吗?我怀疑您的代码中有很大一部分只是关心选择是正确的还是错误的,还有另一部分是做出选择的


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

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


    换句话说:如果连续的结果彼此不依赖,你可能会测试一个
    TRUE
    场景,一个
    FALSE
    场景,然后就可以了。

    我很困惑。如果是随机的,就没有办法让它保持在75%和25%左右,而不让它定义为非随机的……我添加了一个实现这就澄清了这个问题。还有一个问题。你的代码应该在空格中75%的时间返回true,我的意思是在1000次机会中它必须返回750 true。,或者在100次机会中它返回true。,区别是..如果空格是1000,那么在前250次机会中可能返回false..这对100 ch无效重复。我不关心唯一性,我关心随机性。因为在这个简单的例子中只有两个选择,唯一性似乎没有什么用处。如果我计算重复项而不是覆盖它们,这将与解决方案相同#2:运行几次,并断言平均而言,它似乎是您所期望的。@TrystanSpangler-本质上我同意你的解决方案#2。我不确定你在运行迭代测试以推断随机选择这两个选项的次数时有何犹豫。我同意蒂姆·梅多拉的观点。第二个听起来是合乎逻辑的选择。只需做一定的次数,就足以有可能匹配choi你需要ces。在每个选项中,你可以有一个计数器来告诉你有多少是真的或假的,与80%和20%时相比,等等。