How To Set Up Rails With RSpec, Capybara, and Database_cleaner
Configure a test framework in 15 minutes
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.
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
:jsoption 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.
- 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> -Tin your console.
database_cleaner to the Gemfile.
bundle install to install the new gems.
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
spec/rails_helper.rb, ensure that
require 'capybara'are both present. This will allow every test file that requires
rails_helperaccess 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.
false. This tells RSpec not to run every test with a database transaction — we’ll have
database_cleanerhandle 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.
database_cleaner.rb. Here’s what your
spec folder should look like at this point:
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(: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.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
That’s it — you’re ready to start writing tests!