Executing subgroups of RSpec Examples

26 July 2012

When doing TDD it’s important to have a short feedback cycle. Fast tests aren’t just a nice-to-have, they’re an essential part of the cycle. If I have to wait 5 minutes to know whether my tests pass or fail, I’m naturally going to slack off on running them as often as I should. This breaks the red/green/refactor cycle.

Rails integration tests using Capybara and Selenium are painfully slow to run every time your code changes. Thankfully RSpec has a --tag argument that can alleviate this pain.

Any describe, context or it block can be tagged by passing a hash after the description. For example:

describe User, group: 'user' do
  ...
end

To run only the contents of specs tagged with group: 'user', run RSpec with: rspec spec --tag group:user

Tags can be inflected to run everything except specs with a given tag by using the ~. For example: rspec spec --tag ~group:user

Applying this to Rails

Rails & Capybara will automatically tag every spec in the spec/requests directory with type: 'request'. Capybara also uses the js: true tag to determine whether to run a headless test or to run the test through Selenium.

Applying our knowledge about tags and the RSpec runner, you can run everything except the request specs by running:

rspec spec --tag ~type:request

Or you can just ignore the JavaScript specs that run inside a browser by running: rspec spec --tag ~js:true

Happy testing!