如何使用RSpec测试`rand()`?
我有一个类似这样的方法:
def some_method chance = rand(4) if chance == 1 do # logic here else # another logic here end end
当我使用RSpec来测试这个方法时,它内部的rand(4)
总是生成0.我没有测试Rails的rand
方法,我正在测试我的方法。 测试我方法的常见做法是什么?
我会考虑两种方法:
方法1 :
在before :each
块中的srand( seed )
中使用已知的种子值:
before :each do srand(67809) end
这适用于Ruby版本,并在您想要涵盖特定组合的情况下为您提供控制。 我经常使用这种方法 – 考虑一下,这是因为我测试的代码主要使用rand()
作为数据源,而仅使用其次(如果有的话)进行分支。 它也被调用很多,所以对返回值进行逐个调用控制会适得其反,我最终会铲掉许多“看起来随机”的测试数据,可能首先通过调用rand()
生成它rand()
!
您可能希望在至少一个测试场景中多次调用您的方法,以确保您有合理的组合覆盖率。
方法2:
如果由于rand()
输出的值而导致分支点,并且你的断言属于“如果它选择X,那么Y应该发生”,那么在同一个测试套件中模拟rand( n )
也是合理的返回你想要断言的值的东西:
require 'mocha/setup' Kernel.expects(:rand).with(4).returns(1) # Now run your test of specific branch
从本质上讲,这些都是“白盒子”测试方法,它们都要求您知道您的例程在内部使用rand()
。
“黑匣子”测试要困难得多 – 您需要断言行为在统计上是正常的,并且您还需要接受非常广泛的可能性,因为有效的随机行为可能会导致幻像测试失败。
我将提取随机数生成:
def chance rand(4) end def some_method if chance == 1 do # logic here else # another logic here end end
它存根:
your_instance.stub(:chance) { 1 }
这不会将您的测试与rand
的实现细节联系起来,如果您决定使用另一个随机数生成器,那么您的测试不会中断。
似乎最好的想法是使用存根,而不是真正的rand
。 这样你就可以测试你感兴趣的所有值。由于rand
是在Kernel
模块中定义的,你应该使用它来存根:
Kernel.stub(:rand).with(anything) { randomized_value }
在特定的上下文中,您可以使用let
方法定义randomized_value
。
我发现只是短暂的兰德即。 使用Kernel.stub(:rand)作为Samuil的回答并没有最初的工作。 我要测试的代码直接调用rand,例如
random_number = rand
但是,如果我将代码更改为
random_number = Kernel.rand
然后茬工作了。