Friday, February 11, 2011

Agile rspec with let()

Rspec 1.3 has the least-used, yet significant feature called let().

Here's how you set up Rspec 2, for those who have not caught on to let().

describe Friendship do
before :all do
@users = (1..5).collect { Factory(:user) }
end

after :all do
@users.each { |user| user.destroy! }
end

it 'should do something' do
@users.each do |user|
user.should be_valid
end

# Something interesting with @users
end
end

You should be able to replace everything you use @variables for with let(), like this:

describe Friendship do

let(:users) { (1..5).collect { Factory(:user) } }

before :all do
users
end

after :all do
users.each { |user| user.destroy! }
end

it 'should do something' do
@users.each do |user|
user.should be_valid
end

# Something interesting with @users
end
end
I prefer not to preload everything. The tradeoff is slower specs:

describe Friendship do
let(:users) { (1..5).collect { Factory(:user) } }

it 'should do something' do
users.each do |user|
user.should be_valid
end
# Something interesting with @users
end
end
let() cleans up a lot of your code. But where it really shines comes in combination with two things: (1) rspec 2 will preload everthing under spec/support, and (2) Rails 3's secret weapon, ActiveSupport::Concern. You can factor out your let() declarations and share it across your spec, like so:
# Put this in spec/support/application.rb

module SpecHelpers
module Application
extend ActiveSupport::Concern

included do
let(:users) { (1..5).collect { Factory(:user) } }
end
end
end

# spec/friendship_spec.rb
# Rspec 2 automatically loads everything in spec/support
require 'spec_helper'

describe Friendship do
include SpecHelpers::Application

it 'should do something' do
users.each do |user|
user.should be_valid
end
# Something interesting with @users
end
end

# spec/comment_spec.rb
require 'spec_helper'

describe Comment do
include SpecHelpers::Application

it 'should do something' do
users.each do |user|
user.should be_valid
end
# Something interesting with @users
end
end