之前所有vs之前的轨道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 

当我运行这些testing时,所有的东西都是okey,但是如果我之前更改(:all)到之前(:each),每个testing都会失败。我不知道为什么会发生这种情况?

这是错误

  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)在所有块运行之前一次设置实例variables@admission, @project, @creative, @contest_entry

但是:before(:each)每次运行一个块时都会重置before块中的实例variables。

它是一个微妙的区别,但重要的

再次,

 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最重要的细节之一before :all这一切都不是数据库transactional 。 也就是说, before :all任何东西before :all持续到db,而且你必须在after :all方法中手动拆卸。 含义意味着在testing套件完成后,更改不会恢复为下一个testing准备就绪。 这可能会导致错误和testing之间数据交叉污染的问题。 请记住,如果抛出exceptionafter :all callback不被调用。

一个快速testing来演示:

1.截断你适当的数据库表,然后试试这个,

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

2.之后观察数据库,您会注意到模型仍然存在 ! 这是因为你必须包括after :all ,但是如果在你的testing中发生exception,这个callback将不会发生! 任何未来的testing现在都会针对不确定的DB状态运行。

3.现在试试这个,

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

4.testing套件完成后,数据库仍然没有数据 。 CI / CD设置不好。

如果一个testing抛出一个exception并且不能在100个之内完成(防止你的整个testing套件完成),那么可能会出现一些卷积错误。 数据库将处于未知状态。

总之, before :each ,可能都是你想要的。 你的testing会稍微慢一些,但应该是值得的。

详细信息在这里: https : //relishapp.com/rspec/rspec-rails/docs/transactions请参阅: Data created in before(:all) are not rolled back

希望能帮助另一个疲惫的旅行者。

before(:all) ,这确保样本用户在块中的所有testing之前创build一次。 这是速度的优化。