The purpose of this article is a step-by-step guide to get up and running with my preferred rails testing workflow (against rails 5.0.1/rspec 5.3). It could most likely become an application template as it’s mostly just copying and pasting.

This mostly covers testing, but other things will doubtless slip through.

Getting Started

rails new $app_path --database mysql --skip-bundle --skip-test
cd $app_path

At this point, I tend to tidy up the Gemfile somewhat and remove any Gems I’m not going to use. Then replace the groups at the end with something like this:

group :development do
  gem 'spring'
  gem 'spring-commands-rspec'

  gem 'capistrano-rails'

  gem 'guard'
  gem 'guard-rails'
  gem 'guard-rspec'

  gem 'rubocop', require: false
  gem 'reek', require: false

group :development, :test do
  gem 'byebug', platform: :mri

  gem 'rspec-rails', '~> 3.5'
  gem 'rspec-mocks'
  gem 'capybara'
  gem 'poltergeist'

  gem 'forgery'
  gem 'factory_girl_rails'
  gem 'seedbank'

group :test do
  gem 'database_cleaner'
  gem 'simplecov', require: false

Let’s install everything:

bundle install
rails generate rspec:install
mkdir spec/support

Now we need to tell rspec about the various other tools we’ll be using during test runs.

First, we’ll add the following to the top of spec/rails_helper.rb:

ENV['RAILS_ENV'] ||= 'test'

if ENV['RAILS_ENV'] == 'test'
  require 'simplecov'
  SimpleCov.start 'rails'

And the following line after the require 'rspec/rails' line:

Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }

Each of the following files will be loaded by the above, and should be placed in the newly created spec/support - with contents roughly as follows:

# spec/support/capybara.rb
require 'capybara/rails'
require 'capybara/rspec'
require 'capybara/poltergeist'

Capybara.javascript_driver = :poltergeist
# spec/support/factory_girl.rb
RSpec.configure do |config|
  config.include FactoryGirl::Syntax::Methods
# spec/support/database_cleaner.rb
RSpec.configure do |config|
  config.before(:suite) do

  config.before(:each) do
    driver_shares_db_connection_with_specs = (Capybara.current_driver == :rack_test)
    DatabaseCleaner.strategy = driver_shares_db_connection_with_specs ? :transaction : :truncation

  config.append_after(:each) do

Now we have a framework for testing which covers nearly every case. Have a look at the rspec subcommands under rails generate for the types of tests that can be generated.

The Components


A testing framework primarily targeted at BDD with a nifty DSL that lets you write expressive tests.

More than a test runner, rspec does all the heavy lifting to make writing and reading tests easy and fun.


An acceptance test framework for writing tests which simulate user behaviour. It uses a driver to run tests in a browser.

When combined with rspec, we can write a test like this:

RSpec.feature "Widget management", :type => :feature do
  scenario "User creates a new widget" do
    visit "/widgets/new"

    fill_in "Name", :with => "My Widget"
    click_button "Create Widget"

    expect(page).to have_text("Widget was successfully created.")

Here, rspec provides the feature, scenario, and expect methods, while capybara provides the visit, fill_in, click_button and have_text methods.


A library for generating fake data for use in your tests. This is better than hard-coding test data, as it reduces the possibility of accidentally hard-coding your application to make the test pass.

For example:

  #=> ""

See also faker.


A library for setting up test data objects.

Instead of manually creating objects in the database to use during a test run, factory_girl can create them for you (and has various options for persisting them or not).

Note: this is not fast, and should probably be avoided in unit tests in favour of unpersisted ActiveRecord objects, or using rspec mocks.


Sometimes persisting to the database during a test is essential (feature tests) or desirable (you want to test some complex relationship), so ensuring each test begins with a clean slate is vital.

database_cleaner does this using a number of strategies (which we have configured above).


Database seeds. Rails does have this built in, but seedbank gives us a little more structure, and some nice features like dependencies.

To Do