我有一个做了这样的方法:如何使用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
方法,我测试我的方法。 测试我的方法的常用做法是什么?
我有一个做了这样的方法:如何使用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:
使用种子的srand(seed)
在before :each
块已知值:
before :each do
srand(67809)
end
这工作跨越Ruby版本,并在您想要覆盖特定组合时为您提供控制。我大量使用这种方法 - 考虑这一点,那是因为我测试的代码主要使用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()
。
“黑盒子”测试要困难得多 - 您需要断言行为在统计学上没问题,而且您还需要接受非常广泛的可能性,因为有效的随机行为可能会导致幻像测试失败。
看来最好的想法是使用存根,而不是真正rand
。这样你就可以测试你有兴趣在所有的值作为rand
在Kernel
模块定义,你应该使用存根它:
Kernel.stub(:rand).with(anything) { randomized_value }
在特定情况下,你可以用let
方法定义randomized_value
。
我认为这是一个不错的解决方案。我建议一个小改进:'Kernel.stub(:rand).with(任何){randomized_value}' –
谢谢!忘记可选参数。 – samuil
或者如果有多个代码路径并且每个都需要测试,暂时将'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即ie。使用Kernel.stub(:rand)作为Samuil的回答最初并没有工作。我的代码要被测试称为兰特直接例如
RANDOM_NUMBER = RAND
然而,如果我改变的代码
RANDOM_NUMBER = Kernel.rand
然后根部工作。
另请参阅http://stackoverflow.com/questions/6077725/ruby-using-rand-in-code-but-writing-tests-to-verify-probabilities –