In what order does RSpec work before, after, and around hooks?

When I ran into the problem , I decided to check in which order the hooks before and after are executed. This is what I did:

 require "spec_helper" describe "The order:" do before(:all) { puts "before_all" } after(:all) { puts "after_all" } before(:each) { puts "before_each" } after(:each) { puts "after_each" } describe "DESC A" do before { puts "A_before" } it "A_it_1" do expect(1).to eq(1) end it "A_it_2" do expect(1).to eq(1) end end describe "DESC B" do before { puts "B_before" } it "B_it_1" do expect(1).to eq(1) end it "B_it_2" do expect(1).to eq(1) end end end 

and what i got:

 The order: before_all DESC A before_each A_before after_each A_it_1 before_each A_before after_each A_it_2 DESC B before_each B_before after_each B_it_1 before_each B_before after_each B_it_2 after_all 

What's going on here? Why is after_each executed before A_it_1 ?

UPDATE:

adding around(:each) even more fun:

  around(:each) do |example| puts "around_in" example.run puts "around_out" end 

and results:

 The order: before_all DESC A around_in before_each A_before after_each around_out A_it_1 around_in before_each A_before after_each around_out A_it_2 DESC B around_in before_each B_before after_each around_out B_it_1 around_in before_each B_before after_each around_out B_it_2 after_all 
+9
ruby rspec
source share
3 answers

Your conclusion and the official release registered on relishapp.com are correct. What happens is that rspec must run after (: each) es after each example, because an exception in after (: each) will cause the example to fail. Before rspec can display an example on the output, it needs to know whether it is green or red, which means that after (: eaches) it is necessary to run before the description of the description appears on the output.

However, if you put the puts statement in your actual example, you will see that before it (in front of it) they will execute (for example, puts), and then (after each) es, as you would expect, and finally, the description of the example is displayed to the screen.

Like you, I was also confused until I realized that rspec, which prints the example label, does not match what it actually does - the label is printed only after all the previous (: all) s, earlier (: each) es, and after (: each) es are launched as an example.

Note: after (: all) s it starts after printing the example label because they do not affect the test result (a warning is generated that the exception occurred in the hook after (: all), but this does not make the test red).

+6
source share

The RSpec documentation for before and after hooks determines the order in which they are started. However, the RSpec documentation for around hooks does not determine the order in which they are executed.

This specification checks the order in which around , before and after :all and :each , and the examples are executed. When I run it with rspec (-core) 2.14.8, they execute in the order you expect:

 describe "order in which rspec around/before/after hooks run" do before :all do defined?($previous_hook).should be_false # this hook runs first $previous_hook = "before :all" end around :each do |example| $previous_hook.should == "before :all" $previous_hook = "around :each 1" example.run $previous_hook.should == "after :each" $previous_hook = "around :each 2" end before :each do $previous_hook.should == "around :each 1" $previous_hook = "before :each" end it "should not raise an exception or print anything" do $previous_hook.should == "before :each" $previous_hook = "example" end after :each do $previous_hook.should == "example" $previous_hook = "after :each" end after :all do # rspec ignores assertion failures and any other exceptions raised here, so all we can do is puts. # $previous_hook is a global because if it an instance variable it is "before :all" at this point. warn "Previous hook was #{$previous_hook}, NOT around :each 2 as expected" unless $previous_hook == "around :each 2" end end 

Pay attention to some perhaps surprising things:

  • self differs in :all and :each blocks, so I needed to use a global, not an instance variable.
  • after :all (but not before :all ) uses exceptions.
  • Look at all those places .should work! Not that you usually want to use it there.
+4
source share

This has already been answered above, but add the answer in a simple way.

To see the order in which hooks work, you must also add the put statement inside the "it"

So

 describe "The order:" do before(:all) { puts "before_all" } after(:all) { puts "after_all" } before(:each) { puts "before_each" } after(:each) { puts "after_each" } describe "DESC A" do before { puts "A_before" } it "A_it_1" do # expect(1).to eq(1) <<<<---- Change Here puts "Inside the test" end end end 
0
source share

All Articles