developer tip

레일스 rspec 전과 각 전

optionbox 2020. 11. 1. 17:39
반응형

레일스 rspec 전과 각 전


contest_entry_spec.rb

    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

이 테스트를 실행하면 모든 것이 정상이지만 before (: all)를 before (: each)로 변경하면 모든 테스트가 실패합니다. 왜 발생하는지 모르겠습니다.

이것은 오류입니다

 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

before(:all) 모든 예제가 실행되기 전에 블록을 한 번 실행합니다.

before(:each) 파일의 각 사양 전에 블록을 한 번 실행합니다.

before(:all)@admission, @project, @creative, @contest_entry모든 it블록이 실행 되기 전에 인스턴스 변수를 한 번 설정합니다 .

그러나 블록이 실행될 :before(:each)때마다 이전 블록의 인스턴스 변수를 재설정합니다 it.

미묘한 차이지만 중요합니다.

다시,

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) }

의 중요한 세부 사항 before :all은 점입니다 하지 DB transactional. 즉, 그 안의 모든 before :all것은 DB에 유지되며 after :all메서드 에서 수동으로 해체해야합니다 .

Implications mean that after test suites have completed, changes are not reverted ready for later tests. This can result in complicated bugs and issues with cross contamination of data. I.e, If an exception is thrown the after :all callback is not called.

However, before: each is DB transaction.

A quick test to demonstrate:

1. Truncate your appropriate DB table then try this,

  before :all do
    @user = Fabricate(:user, name: 'Yolo')
  end

2. Observe database afterwards the model remains persisted!

after :all is required. However, if an exception occurs in your test this callback will not occur as the flow was interrupted. The database will be left in an unknown state which can be especially problematic with CI/CD environments and automated testing.

3. now try this,

  before :each do
    @user = Fabricate(:user, name: 'Yolo')
  end

4. Now the database remains devoid of data after the test suite is complete. Far better and leaves us with a consistent state after tests run.

In short, before :each, is probably what you want. Your tests will run slightly slower, but it's worth the expense.

Detail here: https://relishapp.com/rspec/rspec-rails/docs/transactions See: Data created in before(:all) are not rolled back

Hope that helps another weary traveller.


before(:all), which ensures that the sample users are created once, before all the tests in the block. This is an optimization for speed.


One thing to note is by default before use before(:each), also in before(:all) the controller instance is not set so the controller methods like request not used.

참고URL : https://stackoverflow.com/questions/16617052/rails-rspec-before-all-vs-before-each

반응형