Cyrus Stoller home about consulting

Upgrading to rspec 3

Here are some quick notes on how I upgraded my rails applications from rspec v2 to rspec v3. Fortunately, I was able to convert > 50 KLOC of specs from the old should syntax to the new preferred expect syntax in under an hour.

Getting started

First, I followed the instructions in the rspec-rails github repository. This mainly involved switching from requiring a spec_helper to requiring a rails_helper and creating a new spec/rails_helper.rb file.

To quickly change require 'spec_helper' to require 'rails_helper' in hundreds of spec files without opening each one individually, I used the following bash one-liner, which I expanded to multiple lines for improved legibility.

for i in $(find spec/ -name \*.rb)
do
  echo $i
  sed -i "" "s/spec_helper/rails_helper/g" $i
done

If you’ve never used sed, I highly recommend taking an hour to get familiar with it. It will save you from doing large search/replace jobs by hand and it also minimizes the impact of human error.

At this point, my specs were still passing.

Next, I upgraded rspec-rails in my Gemfile to gem "rspec-rails", "~> 3.0.1". Running my specs at this point gave me a lot of deprecation warnings and few errors.

To remove the deprecation warnings, I needed to switch from using should to expect. Given the number of specs, I wasn’t keen on doing this manually because it would be tedious and highly error prone. Fortunately, there is a gem to help do this.

Translating ‘should’ to ‘expect’

Install the transpec gem outside of bundler. In other words, there is no need to add it to your Gemfile. The instructions are pretty straight foward.

$ [sudo] gem install transpec
$ transpec
$ git commit -aeF .git/COMMIT_EDITMSG

For most of my projects this was all I needed to do; I ran my specs again and everything was green. But for a few projects, I had a couple of other changes that I needed to make.

Doubles and stubs

In some places I used doubles and stubs in ways that are no longer supported in rspec v3. Granted, these are probably be anti-patterns that I should addresss, but in the meantime here is how I translated them using subclasses. Before, I would have statements like:

before(:all) do
  User.any_instance.stub(:send_confirmation_email_callback).and_return(true)
end

This syntax is no longer supported in in rspec v3. To work around this, I just subclassed the User class in my user_spec.rb and tested that instead.

class TestUser < User
  def send_confirmation_email_callback
    true
  end
end

At least for now all of my specs appear to be functioning properly.

Category Tutorial