How To Set Up Rails With RSpec, Capybara, and Database_cleaner

Configure a test framework in 15 minutes

Angus Morrison
Sep 30, 2019 · 4 min read
Photo by JOSHUA COLEMAN on Unsplash

Sadly for the world, we never got that Matrix prequel where the machines knuckled down and wrote high-quality acceptance tests for their simulation.

I imagine it as a six-month-long, unabridged art piece, replete with many-legged thrashing upon multiple keyboards and punctuated by swearing in binary.

If we had, junior developers everywhere might be less reluctant to get their hands dirty — and keep their code clean — with tests.

Tests matter. Whether you want to stand out from the gaggle of junior devs vying for jobs or you’re just a fan of working code, learning to test your own apps is invaluable.

But, getting to the point where you can begin testing is an ordeal in itself. I recently sat down at my keyboard to knock out the registration, login, and profile flows for a retro social network in Rails.

“A gentle Sunday job,” I thought to myself. Half a day later, bruised, battered, and reeling, I just about had the test framework configured.

Here’s how to do it in 15 minutes.


Tools

Here’s what I use to test simple, JavaScript-free Rails projects:

The newer versions of Rails use MiniTest as the default test framework. I’m more familiar with RSpec. Luckily, the two can be swapped out without much issue.

Everyone’s favorite rodent of unusual size, Capybara is a beautifully readable acceptance test framework that simulates how users interact with your app in-browser. Think visiting pages, filling fields, and clicking buttons.

I use the database_cleaner gem to scrub my test database before each test runs, ensuring a clean slate and stable baseline every time.

By default, RSpec will actually do this for you, running every test with a database transaction and then rolling back that transaction after it finishes.

There are a few quirks to catch you off-guard, however:

  • Data created within an RSpec before(:each) Hook does get rolled back after each test — great.
  • Data created within a before(:all) Hook does not get rolled back. Unless you manually handle it, that data may start interfering with other tests in the suite.
  • If you’re using Capybara with the :js option to test with Selenium or WebKit, RSpec’s transactional cleaner simply won’t work.

If you want to configure your own cleaner, I’ve included the essentials of database_cleaner below.


Getting Started

  1. To use RSpec, create your new Rails project without the default test framework. It’s much simpler to do this now than to perform a full-scale exorcism to get rid of it later. Run rails new <project_name> -T in your console.

2. Add rspec-rails, capybara, and database_cleaner to the Gemfile.

3. Run bundle install to install the new gems.

4. Run bundle exec rails g rspec:install to initialize RSpec and generate the spec folder in your project directory. This is where all of your tests will live.


Configure RSpec and Capybara

  1. In spec/rails_helper.rb, ensure that require 'rspec/rails' and require 'capybara' are both present. This will allow every test file that requires rails_helper access to RSpec and Capybara without requiring them individually.

2. Capybara tests are often called “feature tests” because, unlike unit tests, they test complex program behaviors that rely on multiple systems within your code. Go ahead and create a spec/features directory to store these tests in later.


Configure database_cleaner for RSpec

Database_cleaner takes some more love to get working.

  1. In rails_helper.rb, set config.use_transactional_fixtures to false. This tells RSpec not to run every test with a database transaction — we’ll have database_cleaner handle that instead.

2. Create a new directory: spec/support. To keep the project in good order, this is where we’ll store our database_cleaner configuration file.

3. In spec/support, create database_cleaner.rb. Here’s what your spec folder should look like at this point:

3. Inside database_cleaner.rb, open this code block:

4. Inside the block, add the following:

This instructs RSpec to use database_cleaner to “truncate” the database before every test suite — it empties every table entirely. This is a brute-force approach to database cleaning but for personal projects, it will serve just fine.

If you’re using Active Record, the except statement is essential. Without it, the database_cleaner will destroy Active Record’s environment data, resulting in a NoEnvironmentInSchemaError every time your tests run.

5. Next, add:

On a test-by-test basis (i.e. before(:each), not before(:suite)) , truncation is overkill.

Here, we set the database_cleaner strategy to transaction, which means every test will create a database transaction that will simply be rolled back when it ends, as if it never happened.

DatabaseCleaner.start and DatabaseCleaner.end are simply the triggers to start the cleaning process before and after each test.

Here’s how the finished database_cleaner.rb file should look (my undying thanks to Virtuous Code for their help on this one):

6. Finally, tell rails_helper.rb where to find database_cleaner.rb with require 'support/database_cleaner'.

That’s it — you’re ready to start writing tests!


Better Programming

Advice for programmers.

Angus Morrison

Written by

Software Engineer @ Bamboo. Recovering product manager and UX Consultant.

Better Programming

Advice for programmers.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade