Skip to main content

before and after hooks

Use before and after hooks to execute arbitrary code before and/or after the body of an example is run:

before(:example) # run before each example
before(:context) # run one time only, before all of the examples in a group

after(:example) # run after each example
after(:context) # run one time only, after all of the examples in a group

before and after blocks are called in the following order:

before :suite
before :context
before :example
after :example
after :context
after :suite

A bare before or after hook defaults to the :example scope.

before and after hooks can be defined directly in the example groups they should run in, or in a global RSpec.configure block. Note that the status of the example does not affect the hooks.

WARNING: Setting instance variables are not supported in before(:suite).

WARNING: Mocks are only supported in before(:example).

WARNING: around hooks will execute before any before hooks, and after any after hooks regardless of the context they were defined in.

Note: the :example and :context scopes are also available as :each and :all, respectively. Use whichever you prefer.

Define before(:example) block

Given a file named "before_example_spec.rb" with:

require "rspec/expectations"

class Thing
def widgets
@widgets ||= []
end
end

RSpec.describe Thing do
before(:example) do
@thing = Thing.new
end

describe "initialized in before(:example)" do
it "has 0 widgets" do
expect(@thing.widgets.count).to eq(0)
end

it "can accept new widgets" do
@thing.widgets << Object.new
end

it "does not share state across examples" do
expect(@thing.widgets.count).to eq(0)
end
end
end

When I run rspec before_example_spec.rb

Then the examples should all pass.

Define before(:context) block in example group

Given a file named "before_context_spec.rb" with:

require "rspec/expectations"

class Thing
def widgets
@widgets ||= []
end
end

RSpec.describe Thing do
before(:context) do
@thing = Thing.new
end

describe "initialized in before(:context)" do
it "has 0 widgets" do
expect(@thing.widgets.count).to eq(0)
end

it "can accept new widgets" do
@thing.widgets << Object.new
end

it "shares state across examples" do
expect(@thing.widgets.count).to eq(1)
end
end
end

When I run rspec before_context_spec.rb

Then the examples should all pass

When I run rspec before_context_spec.rb:15

Then the examples should all pass.

Failure in before(:context) block

Given a file named "before_context_spec.rb" with:

RSpec.describe "an error in before(:context)" do
before(:context) do
raise "oops"
end

it "fails this example" do
end

it "fails this example, too" do
end

after(:context) do
puts "after context ran"
end

describe "nested group" do
it "fails this third example" do
end

it "fails this fourth example" do
end

describe "yet another level deep" do
it "fails this last example" do
end
end
end
end

When I run rspec before_context_spec.rb --format documentation

Then the output should contain "5 examples, 5 failures"

And the output should contain:

an error in before(:context)
fails this example (FAILED - 1)
fails this example, too (FAILED - 2)
nested group
fails this third example (FAILED - 3)
fails this fourth example (FAILED - 4)
yet another level deep
fails this last example (FAILED - 5)
after context ran

When I run rspec before_context_spec.rb:9 --format documentation

Then the output should contain "1 example, 1 failure"

And the output should contain:

an error in before(:context)
fails this example, too (FAILED - 1)

Failure in after(:context) block

Given a file named "after_context_spec.rb" with:

RSpec.describe "an error in after(:context)" do
after(:context) do
raise StandardError.new("Boom!")
end

it "passes this example" do
end

it "passes this example, too" do
end
end

When I run rspec after_context_spec.rb

Then it should fail with:

An error occurred in an `after(:context)` hook.
Failure/Error: raise StandardError.new("Boom!")

StandardError:
Boom!
# ./after_context_spec.rb:3

A failure in an example does not affect hooks

Given a file named "failure_in_example_spec.rb" with:

RSpec.describe "a failing example does not affect hooks" do
before(:context) { puts "before context runs" }
before(:example) { puts "before example runs" }
after(:example) { puts "after example runs" }
after(:context) { puts "after context runs" }

it "fails the example but runs the hooks" do
raise "An Error"
end
end

When I run rspec failure_in_example_spec.rb

Then it should fail with:

before context runs
before example runs
after example runs
Fafter context runs

Define before and after blocks in configuration

Given a file named "befores_in_configuration_spec.rb" with:

require "rspec/expectations"

RSpec.configure do |config|
config.before(:example) do
@before_example = "before example"
end
config.before(:context) do
@before_context = "before context"
end
end

RSpec.describe "stuff in before blocks" do
describe "with :context" do
it "should be available in the example" do
expect(@before_context).to eq("before context")
end
end
describe "with :example" do
it "should be available in the example" do
expect(@before_example).to eq("before example")
end
end
end

When I run rspec befores_in_configuration_spec.rb

Then the examples should all pass.

before/after blocks are run in order

Given a file named "ensure_block_order_spec.rb" with:

require "rspec/expectations"

RSpec.describe "before and after callbacks" do
before(:context) do
puts "before context"
end

before(:example) do
puts "before example"
end

before do
puts "also before example but by default"
end

after(:example) do
puts "after example"
end

after do
puts "also after example but by default"
end

after(:context) do
puts "after context"
end

it "gets run in order" do

end
end

When I run rspec --format progress ensure_block_order_spec.rb

Then the output should contain:

before context
before example
also before example but by default
also after example but by default
after example
.after context

before/after blocks defined in configuration are run in order

Given a file named "configuration_spec.rb" with:

require "rspec/expectations"

RSpec.configure do |config|
config.before(:suite) do
puts "before suite"
end

config.before(:context) do
puts "before context"
end

config.before(:example) do
puts "before example"
end

config.after(:example) do
puts "after example"
end

config.after(:context) do
puts "after context"
end

config.after(:suite) do
puts "after suite"
end
end

RSpec.describe "ignore" do
example "ignore" do
end
end

When I run rspec --format progress configuration_spec.rb

Then the output should contain:

before suite
before context
before example
after example
.after context
after suite

before/after context blocks are run once

Given a file named "before_and_after_context_spec.rb" with:

RSpec.describe "before and after callbacks" do
before(:context) do
puts "outer before context"
end

example "in outer group" do
end

after(:context) do
puts "outer after context"
end

describe "nested group" do
before(:context) do
puts "inner before context"
end

example "in nested group" do
end

after(:context) do
puts "inner after context"
end
end

end

When I run rspec --format progress before_and_after_context_spec.rb

Then the examples should all pass

And the output should contain:

outer before context
.inner before context
.inner after context
outer after context

When I run rspec --format progress before_and_after_context_spec.rb:14

Then the examples should all pass

And the output should contain:

outer before context
inner before context
.inner after context
outer after context

When I run rspec --format progress before_and_after_context_spec.rb:6

Then the examples should all pass

And the output should contain:

outer before context
.outer after context

Nested examples have access to state set in outer before(:context)

Given a file named "before_context_spec.rb" with:

RSpec.describe "something" do
before :context do
@value = 123
end

describe "nested" do
it "access state set in before(:context)" do
expect(@value).to eq(123)
end

describe "nested more deeply" do
it "access state set in before(:context)" do
expect(@value).to eq(123)
end
end
end

describe "nested in parallel" do
it "access state set in before(:context)" do
expect(@value).to eq(123)
end
end
end

When I run rspec before_context_spec.rb

Then the examples should all pass.

before/after context blocks have access to state

Given a file named "before_and_after_context_spec.rb" with:

RSpec.describe "before and after callbacks" do
before(:context) do
@outer_state = "set in outer before context"
end

example "in outer group" do
expect(@outer_state).to eq("set in outer before context")
end

describe "nested group" do
before(:context) do
@inner_state = "set in inner before context"
end

example "in nested group" do
expect(@outer_state).to eq("set in outer before context")
expect(@inner_state).to eq("set in inner before context")
end

after(:context) do
expect(@inner_state).to eq("set in inner before context")
end
end

after(:context) do
expect(@outer_state).to eq("set in outer before context")
end
end

When I run rspec before_and_after_context_spec.rb

Then the examples should all pass.

Exception in before(:example) is captured and reported as failure

Given a file named "error_in_before_example_spec.rb" with:

RSpec.describe "error in before(:example)" do
before(:example) do
raise "this error"
end

it "is reported as failure" do
end
end

When I run rspec error_in_before_example_spec.rb

Then the output should contain "1 example, 1 failure"

And the output should contain "this error".