2013-06-30 55 views
0

我已经在游戏下面的方法,我发展:RSpec的测试`rand`内`rand`

def search 
    if rand(5) == 0 
     weapon = Weapon.offset(rand(Weapon.count)).first 
     users_weapon = UsersWeapon.create(user_id: self.id, weapon_id: weapon.id, ammo: weapon.max_ammo) 
     self.users_weapons << users_weapon 
     { :success => 'true', :weapon => users_weapon } 
    else 
     { :success => 'false' } 
    end 
    end 

正如你所看到的,我有两个rand的存在。
现在,当我试图使用RSpec来测试它,我想测试下它:

context 'when searches location' do 
    subject(:user) { FactoryGirl.create :User } 
    before { FactoryGirl.create :knife } 
    before { FactoryGirl.create :pistol } 

    context 'when finds knife' do 
    before { srand(2) } 
    it { user.search[:weapon].weapon.name.should == 'Knife' } 
    end 

    context 'when finds pistol' do 
    before { srand(3) } 
    it { p user.search[:weapon][:name].should == 'Pistol' } 
    end 

不管是什么我通过在srand这里,它只能在以下两种方法之一:
a)返回Pistol

b)返回零。

我想独立存根这些rand s。我不想在每个环境中种下一个weapon,因为我想实际测试随机武器选择。我该如何执行它?

+0

你想对你的随机武器选择做出什么断言?即他们想要展示并潜在维护的行为是什么?如果你想断言一些关于随机性的东西,那么这是一个不同的问题,它想要断言每个代码路径被执行时会发生什么。 –

回答

0

几乎所有rand()是伪随机生成,其随机性取决于你启动它们,停止与相同数量的种子,而不是使用类似的时间(srand(gettime()))或东西,每次改变种子。

PS:gettime()应该返回一个int,你必须做出Ruby的什么正常时间函数的包装返回将其转换为int

2

使用意向为你的方法揭示的名字,然后嘲笑这种方法代替兰德

def search 
    if rand(5) == 0 
    weapon = Weapon.find_random 
    # ... 

class Weapon 
    # ... 
    def self.find_random 
    self.offset(rand(self.count)).first 

现在你可以很容易地嘲笑Weapon.find_random

而且如果需要的话,以后容易改变

您的实现
class Weapon 
    # ... 
    def self.find_random 
    # postgres 
    self.order("RANDOM()").limit(1).first 
    # mysql 
    self.order("RAND()").limit(1).first