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.
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.
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.
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.