Faster Capybara Specs

How to use the database_cleaner gem without slowing everything down.

Being able to drive a real web browser using Rspec and Capybara is great for testing JavaScript features in Rails. But have you noticed a drastic slowdown in the execution of your specs after setting up Capybara? Here’s how to speed things back up.

Well-intentioned, but slow

If you’ve used Capybara and Rspec, you probably found that transactional fixtures won’t work with JavaScript specs. A quick search on the web will reveal this workaround:1

# Gemfile
gem 'database_cleaner', group: :test

# spec_helper.rb -- This workaround is slow!
RSpec.configure do |config|
  # ...
  config.use_transactional_fixtures = false

  config.before(:suite) do
    DatabaseCleaner.strategy = :truncation
  end

  config.before(:each) do
    DatabaseCleaner.start
  end

  config.after(:each) do
    DatabaseCleaner.clean
  end
end

However, this workaround is a very blunt instrument: it tells Rspec to truncate the database after every spec. But we don’t need the workaround for every spec, we need it only for JavaScript specs.

A faster solution

The trick is to still use the database_cleaner gem, but specify the slow :truncation strategy only when we need it, and fall back to the fast :transaction strategy otherwise. Here’s how:

RSpec.configure do |config|
  # ...
  config.use_transactional_fixtures = false

  config.before(:each) do
    DatabaseCleaner.strategy = if example.metadata[:js]
      :truncation
    else
      :transaction
    end
    DatabaseCleaner.start
  end

  config.after(:each) do
    DatabaseCleaner.clean
  end
end

Notice how we use the metadata to test whether or not an example uses JavaScript (i.e. whether js: true was specified). Using this metadata, it’s easy to choose the appropriate database strategy on an example-by-example basis.

The result

Here’s how long it took to run rake spec on one of my projects before we adopted this solution:

Finished in 3 minutes 39.44 seconds

And after:

Finished in 41.27 seconds

That’s an 80% speedup!


  1. This sample spec_helper.rb workaround is taken from RailsCasts episode #257. If you aren’t familiar with Capybara’s JavaScript testing abilities, or you’re new to Capybara-based integration testing in general, definitely check out the screencast. Then come back to this article to learn about my speedup. 

Share this? Copy link

Feedback? Email me!

Hi! 👋 I’m Matt Brictson, a software engineer in San Francisco. This site is my excuse to practice UI design, fuss over CSS, and share my interest in open source. I blog about Rails, design patterns, and other development topics.

Recent articles

RSS
View all posts →

Open source projects

mattbrictson/rails-template

App template for Rails 7 projects; best practices for TDD, security, deployment, and developer productivity. Now with optional Vite integration! ⚡️

1,055
Updated 1 month ago

mattbrictson/tomo

A friendly CLI for deploying Rails apps ✨

360
Updated 20 days ago

More on GitHub →