The Guard gem watches for when you modify code or test files, and automatically re-runs tests that could be affected by those changes immediately, so you get instant feedback if you just broke something. It’s a great tool for supporting true TDD but a bit tricky to set up.

Add to the test and development groups in your Gemfile and then rerun bundle install:

group :test, :development do
  gem 'guard'
  gem 'guard-rspec', require: false
  gem 'guard-cucumber'
  gem 'guard-shell'
end

Run guard init rspec and then guard init cucumber to populate an initial Guardfile, and add that file to your repo.

Guard works with plugins that tell it how to integrate with different testing tools. In the Guardfile, the blocks named group rspec, group cucumber, etc. name the different plugins and tools. Within each plugin’s block, there are one or more blocks guard :tool, :cmd => _command-to-run-tests that have the structure:

watch(regexp matching filenames) { _tests to run when those files change_ }

If you look at the default provided block for Rspec, you should be able to discern the following rules:

  • When a controller file changes, run all specs for that controller

  • When helper files change, run all specs

  • When routes file(s) change, run all route specs

  • When application_controller.rb changes, rerun all controller specs (since all controllers inherit from ApplicationController)

Basically you are telling Guard which tests may cover functionality in the files that changed.

Start up Guard by running bundle exec guard. Make a trivial change to one of your project files to make a test fail (e.g. introduce a syntax error), and watch Guard re-run the matching specs.

Running only a subset of specs

In the :cmd argument to guard :rspec block, note the option :failed_mode => :focus. This means: If one or more specs failed as a result of the most recent test run, on future runs try only those failed specs, until they pass; then go back to running all affected specs.

To make this work, we have to do two things. First, we have to tell RSpec to enable focus mode, in which only specs annotated with :focus => true are run. In spec/rails_helper.rb, add in the RSpec configuration block:

  config.filter_run :focus => true
  config.run_all_when_everything_filtered = true

Then, when Guard has just run some tests and hit a failure, annotate a single example (it "does something" do...end) or a group of examples (describe "something" do...end) with :focus => true. The next time you change a file that might affect these specs, only the specs so annotated will be run.

When those specs go back to passing, remove :focus => true and the next Guard-triggered run will re-run all affected specs.