5 Minutes Hack to Speed Up RSpec in Rails 5 Using In-memory SQLite

Here is the story : you have a Rails 5 app that uses RSpec, but your RSpec suite is getting slower and slower to run. You’ve already considered some solutions :

  • Use SQLite in memory for your test env.
1
2
3
test:
  adapter: sqlite3
  database: ":memory:"

That’s the most straightforward thing to do, but unfortunately, if you are sharing your test env with Cucumber, you might want to use a production like DB with Cucumber (PostgreSQL or whatever). So unless you are ready to setup a new env for cucumber (which I tried and don’t recommend) you’re stuck.

  • Use mocks. That’s surely going to work, it’s going to make your test hell of a lot faster ! It will also make your tests a lot more fragile and more expensive to maintain … If you want to read more about why I think mocks are a bad idea, just have a look at these posts.

The hack

Here is a third alternative, I’ve already written about it, but here it comes updated and tested for Rails 5 :

  1. Don’t change anything to your config/database.yml
  2. Obviously, you’ll need to add sqlite3 to your Gemfile
  3. At the beginning of your spec/rails_helper.rb, replace
1
2
3
# Checks for pending migration and applies them before tests are run.
# If you are not using ActiveRecord, you can remove this line.
ActiveRecord::Migration.maintain_test_schema!

with

1
2
3
4
5
# In order to keep the same RAILS_ENV for rspec and cucumber,
# patch the connection to use sqlite in memory when running rspec
ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
ActiveRecord::Schema.verbose = false
load "#{Rails.root.to_s}/db/schema.rb"

That’s it ! Run your specs … not bad for a 5 minutes investment !

One more thing …

If you need even more speed, you can now run your specs in parallel in different processes ! Each in-memory SQLite DB is bound to its process, so unlike a real PostgreSQL dev DB, you won’t get any conflicts between your tests ;–)

Comments