How I Fast Test with Rails
Corey Haines has been busy bringing the gospel of fast tests to the Rails world. A few others have since taken up the call and written up their own approach. This is all wonderful but I didn’t quite feel like I could get behind the implementations I’ve seen. So I decided to work out an approach that would fit with my workflow. This article is the result.
What I Want
All the approaches I’ve seen required some change in how your specs & code are organized. This would require subtle changes to my workflow. While not insurmountable, I figured there had to be a cleaner way.
My goals going in were as follows:
- Navigate my code/specs with existing rails-vim shortcuts
- Work with code in app/models as well as lib
- No extra command line requirements
- Work with my existing guard config
What I Did
Move common RSpec config to spec/config.rb.
# spec/config.rb
RSpec.configure do |config|
config.mock_with :rspec
config.treat_symbols_as_metadata_keys_with_true_values = true
end
Create spec/fast_spec_helper.rb. It adds app/models to the load path & requires common RSpec config. The rspec command already includes the lib directory so we don’t need to worry about that.
# spec/fast_spec_helper.rb
$:.push File.expand_path("../../app/models", __FILE__)
require 'config'
Specs go in spec/models like normal & include the fast_spec_helper as well as the model file.
# spec/models/hello_spec.rb
require 'fast_spec_helper'
require 'hello'
describe Hello do
its(:world) { should == 'hello world' }
end
Implementation goes in app/models as you’d expect.
# app/models/hello.rb
class Hello
def world
"hello world"
end
end
And that’s it! You can now run this fast spec via rspec spec/models/hello_spec.rb same as you ever would. No need to change your Guards and you can use rails-vim’s :A/:Runit to jump around your fast specs & their implementation.
Bonus Points: Split the Fast & Slow
What if you want to run all of your fast, isolated tests before committing to running the slow, framework dependant tests? Easy, just leverage RSpec 2’s meta-data by tagging your examples with fast: true.
# spec/models/hello_spec.rb
require 'fast_spec_helper'
require 'hello'
describe Hello, fast: true do
its(:world) { should == 'hello world' }
end
~/$ rspec spec -t fast
~/$ rspec spec -t ~fast