Speed Up RSpec With Set()

I enjoy using the let() method as it makes my specs easier to read and maintain than setting up instance variables in before(:each) blocks. The let() method can be used like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
describe Account do
  let(:account) { Factory(:account) }

  subject { account }

  it { should be_enabled }

  context "when #disable!" do
    before do
      account.disable!
    end

    it { should be_disabled }
  end
end

My main concern was that the block gets evaluated everytime the method is called. In the example above, Factory(:account) will run and create a new record for every single spec.

To increase our specs performances let’s refactor this and setup the account in a before(:all) block.

1
2
3
4
5
6
7
8
describe Account do
  before(:all) do
    @account = Factory(:account)
  end

  let(:account) { @account.reload }
  #...
end

The account is now setup once before the specs get run. Each spec will be run in a separate transaction to prevent side effects. The account will be rolled back to its initial state before each spec then. Since ActiveRecord is not aware of the rollback we reload the account object from the database every time it’s called.

Specs are now faster but I want them to be as pretty as they were. Let’s make a little helper called set().

Sweeeet! You can now write the following:

1
2
3
4
5
describe Account do
  set(:account) { Factory(:account) }

  #...
end

The records created by set() will remain in your database. You can use DatabaseCleaner with the :truncation strategy to clean up your database. So far in RSpec 2.0, before(:all) runs before all describe/context/it while after(:all) runs after every single describe/context/it. Just make sure that you call DatabaseCleaner.clean in a before(:all) or after(:suite) blocks then. :)

I hope you’ll enjoy using this little helper. It’s very young and it has been tested with RSpec 2 only, so fill free to fill up the comments with enhancements and bug reports!

rspec-set is now available as a gem

Comments