2013-05-17 72 views
51

contest_entry_spec.rb前rspec的軌道前的所有VS各

require 'spec_helper' 

    describe ContestEntry do 

     before(:all) do 
     @admission=Factory(:project_admission) 
     @project=Factory(:project_started, :project_type => @admission.project_type) 
     @creative=Factory(:approved_creative, :creative_category => @admission.creative_category) 
     @contest_entry=Factory(:contest_entry, :design_file_name => 'bla bla bla', :owner => @creative, :project => @project) 
     end 

     context 'non-specific tests' do 
     subject { @contest_entry } 
     it { should belong_to(:owner).class_name('User') } 
     it { should belong_to(:project) } 
     it { should have_many(:entry_comments) } 

     it { should validate_presence_of(:owner) } 
     it { should validate_presence_of(:project) } 
     it { should validate_presence_of(:entry_no) } 
     it { should validate_presence_of(:title) } 

     end 
end 

當我運行這些測試,一切都好,但如果我改變之前(:所有)之前(:每個)每次測試將失敗我不知道它爲什麼會發生?

這是錯誤

Failure/Error: @contest_entry=Factory(:contest_entry, :design_file_name => 'bla bla bla', :owner => @creative, :project => @project) 
    ActiveRecord::RecordInvalid: 
     Validation Failed: User is not allowed for this type of project 

回答

85

before(:all)運行所有的實施例中運行之前的塊中的一個的時間。

before(:each)運行該文件中每個規格的前塊一次

before(:all)設置實例變量的所有it塊的前@admission, @project, @creative, @contest_entry一個時間運行。

但是,每次運行it塊時,:before(:each)都會重置before塊中的實例變量。

它是一種微妙的區別,但重要的

再次,

before(:all) 
#before block is run 
it { should belong_to(:owner).class_name('User') } 
it { should belong_to(:project) } 
it { should have_many(:entry_comments) } 

it { should validate_presence_of(:owner) } 
it { should validate_presence_of(:project) } 
it { should validate_presence_of(:entry_no) } 
it { should validate_presence_of(:title) } 

before(:each) 
# before block 
it { should belong_to(:owner).class_name('User') } 
# before block 
it { should belong_to(:project) } 
# before block 
it { should have_many(:entry_comments) } 
# before block 

# before block 
it { should validate_presence_of(:owner) } 
# before block 
it { should validate_presence_of(:project) } 
# before block 
it { should validate_presence_of(:entry_no) } 
# before block 
it { should validate_presence_of(:title) } 
+0

如果您對任何問題有任何疑問,請告知我。很高興幫助 – fontno

3

before(:all),這確保了樣本用戶創建一次,塊中的所有測試之前。這是對速度的優化。

14

before :all最重要的細節之一是它是而不是 DB transactional。也就是說,before :all中的任何內容都會保留到數據庫中,並且您必須手動拆除after :all方法。含義意味着在測試套件完成之後,更改不會恢復爲下一次測試準備就緒。這可能會導致錯誤和測試之間數據交叉污染的問題。請記住,如果發生異常,則不會調用after :all回調。

快速測試表明:

截斷那麼你適當的數據庫表試試這個,

before :all do 
    @user = Fabricate(:user, name: 'Happy Fun Pants') 
    end 

2.觀察數據庫之後,你會發現模型仍然堅持!?這是因爲您必須包含after :all,但是如果在測試中發生異常,則不會發生此回調!任何未來的測試現在都會針對不確定的DB狀態運行。

現在試試這個,

before :each do 
    @user = Fabricate(:user, name: 'Happy Fun Pants') 
    end 

4.現在數據庫保持沒有數據的測試套件後完成。 CI/CD設置不佳。

如果測試引發異常並且未能在100之間完成(防止完成整個測試套件),則可能會出現卷積錯誤。數據庫將處於未知狀態。

總之,before :each,可能是你想要的。您的測試運行速度稍慢,但應該值得。

這裏詳細: https://relishapp.com/rspec/rspec-rails/docs/transactions 參見:Data created in before(:all) are not rolled back

希望幫助另一疲憊的旅客。

+0

這個技巧可以拯救我的一天!只需在之前寫入(:每個) –