2013-05-17 1 views
51

contest_entry_spec.rb前レールRSpecの前に、すべての対各

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)ある例のすべてが実行される前にブロック1回実行されます。

before(:each)

before(:all)itすべてのブロックの前に@admission, @project, @creative, @contest_entry 1時間が実行されているインスタンス変数を設定ファイルにあなたのスペックのそれぞれの前にブロック1時間を実行します。

ただし、ブロックが実行されるたびに、: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の最も重要な部分の1つは、ではなく、 DB transactionalです。つまり、before :all内のものはすべてdbにとどまり、after :allメソッドで手動で解凍する必要があります。含意とは、テストスイートが完了した後、次回のテストのために変更を元に戻すことができないことを意味します。これにより、テスト間のデータの相互汚染に関する複雑なバグや問題が発生する可能性があります。例外がスローされた場合、after :allコールバックは呼び出されません。

実証するための簡単なテスト:

1.

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

2.はその後データベースを守って、これを試してみてください、あなたの適切なDBのテーブルを切り捨て、あなたはモデルに気づくでしょう残っている残っている!?これは、after :allを含める必要があるためですが、テストで例外が発生した場合でも、このコールバックは発生しません。将来のテストは不確かなDB状態に対して実行されるようになりました。

3.

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

このヒントは私の一日を節約!直前に書く(:each) –

関連する問題