Read more

Using before(:context) / before(:all) in RSpec will cause you lots of trouble unless you know what you are doing

Arne Hartherz
September 20, 2012Software engineer at makandra GmbH

TL;DR Avoid before(:context) (formerly before(:all)), use before(:example) (formerly before(:each)) instead.

Illustration UI/UX Design

UI/UX Design by makandra brand

We make sure that your target audience has the best possible experience with your digital product. You get:

  • Design tailored to your audience
  • Proven processes customized to your needs
  • An expert team of experienced designers
Read more Show archive.org snapshot

If you do use before(:context), you need to know what you are doing and take care of any cleanup yourself.

Why?

Understand this:

  • before(:context) is run when the context/describe block begins,
  • before(:context) is run outside of transactions, so data created here will bleed into other specs
  • before(:example) is run before each spec inside it,

Generally, you'll want a clean setup for each spec so that they are independent of other specs in the same context.

Example

Consider this spec:

describe User, 'something' do
  before :context do
    @user = User.make
  end

  it 'should so something' do
    # ...
  end

  it 'should so something else' do
    # ...
  end
end

If you do that, @user will not be re-created for each test. Obviously, this has significant downsides, mostly that changes of one test on that record will bleed into the next one. \
Also, when using DatabaseCleaner with the :deletion strategy, the record will be gone after the first spec.

Doing it right

before(:example) is the right choice in most cases. So, for the above example we say the following and all is well.

describe User, 'something' do
  before :example do
    @user = User.make
  end

  # ...
end

Furthermore, you will probably run into trouble with your RSpec configuration block that does things in config.before(:example), as this will also be run after your individual spec's before(:context) block did things and might revert changes.

Always use before(:example) unless you are totally sure of the impact your before(:context) block has.

Posted by Arne Hartherz to makandra dev (2012-09-20 10:54)