Ruby-on-rails rails rspec before all vs before each

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16617052/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 22:00:26  来源:igfitidea点击:

rails rspec before all vs before each

ruby-on-railsrspec

提问by Johnny Cash

contest_entry_spec.rb

Competition_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

When I run these tests everything is okey but if I change before(:all) to before(:each) every test will be failed.I don't know why it happens?

当我运行这些测试时,一切正常,但如果我将 before(:all) 更改为 before(:each),则每个测试都将失败。我不知道为什么会这样?

This is the error

这是错误

 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

回答by fontno

before(:all)runs the block one time before all of the examples are run.

before(:all)在所有示例运行之前运行该块一次。

before(:each)runs the block one time before each of your specs in the file

before(:each)在文件中的每个规范之前运行该块一次

before(:all)sets the instance variables @admission, @project, @creative, @contest_entryone time before all of the itblocks are run.

before(:all)@admission, @project, @creative, @contest_entry在所有it块运行之前设置实例变量一次。

However, :before(:each)resets the instance variables in the before block every time an itblock is run.

但是,:before(:each)每次it运行块时都会重置 before 块中的实例变量。

Its a subtle distinction but important

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

again,

再次,

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

回答by wired00

An important detail of before :allis that it's notDB transactional. I.e, anything within the before :allpersists to the DB and you must manually tear down in the after :allmethod.

的一个重要细节before :all是它不是DB transactional。即,任何内容都before :all保留在数据库中,您必须在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 :allcallback is not called.

暗示意味着在测试套件完成后,更改不会恢复为以后的测试做好准备。这可能会导致复杂的错误和数据交叉污染的问题。即,如果抛出异常,after :all则不会调用回调。

However, before: eachisDB transaction.

但是,before: eachDB事务。

A quick test to demonstrate:

一个快速测试来证明:

1.Truncate your appropriate DB table then try this,

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

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

2.Observe database afterwards the model remains persisted!

2.之后观察数据库,模型保持持久化

after :allis 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.

after :all是必须的。但是,如果在您的测试中发生异常,则此回调将不会发生,因为流程已中断。数据库将处于未知状态,这在 CI/CD 环境和自动化测试中尤其成问题。

3.now try this,

3.现在试试这个,

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

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

4.现在测试套件完成后数据库仍然没有数据。好得多,并且在测试运行后让我们保持一致的状态。

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

简而言之,before :each, 可能就是您想要的。您的测试运行速度会稍慢一些,但值得付出代价。

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

详情请见:https: //relishapp.com/rspec/rspec-rails/docs/transactions见:Data created in before(:all) are not rolled back

Hope that helps another weary traveller.

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

回答by Jazib Bashir

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

before(:all),这确保在块中的所有测试之前创建一次示例用户。这是对速度的优化。

回答by shiva kumar

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.

需要注意的一件事是在使用 before(:each) 之前默认情况下,也在 before(:all) 中未设置控制器实例,因此未使用请求等控制器方法。