2013-06-30 93 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