sviluppiamo comunicazione con weLaika Advertising

Run RSpec tests in parallel

Tag: ruby on rails, ruby, testing, rspec
Fabrizio Monti -

We recently worked on a big Rails application with a lot of RSpec tests (mostly integration ones) and we were looking for a way to reduce the test suite execution time.

So we ended up trying parallel_test gem and it has drastically reduced the suite running time!

ParallelTests splits tests into even groups (by number of lines or runtime) and runs each group in a single process with its own database.

It might not be a magic solution for all projects - all in all, loading multiple Rails applications take some time! - but it worked very well in our case and this is how we set it up.

Setup

Add gem to Gemfile:

1
gem 'parallel_tests', group: [:development, :test]

If your computer has, for instance, four cores, ParallelTests will use four databases. Each ParallelTests process will use its own environment variable (TEST_ENV_NUMBER) to identify which database it’s going to use.

So we need to edit our database.yml file:

1
2
test:
  database: my_app_test<%= ENV['TEST_ENV_NUMBER'] %>

Create databases and load schema:

1
2
rake parallel:create
rake parallel:prepare

Create a new file called .rspec_parallel:

1
2
3
4
5
--color
--require spec_helper
--format progress
--format ParallelTests::RSpec::RuntimeLogger --out tmp/parallel_runtime_rspec.log
--format ParallelTests::RSpec::SummaryLogger --out tmp/spec_summary.log

RuntimeLogger will keep track of how long each test takes to run and ParallelTests will use this log to split the tests evenly between processes, so that each process should finish around the same time.

SummaryLogger, instead, will output a nice log for each ParallelTests process.

Now we can run our tests in parallel:

1
rake parallel:spec

Spring

To use Spring with ParallelsTest you have to patch it. We didn’t notice a significant improvement so we didn’t patch it. Feel free to try yourself both solutions.

Binstub

We can create a binstub if we feel more comfortable with it:

1
2
3
bundle binstub parallel_tests
# use binstub instead of rake task
bin/parallel_rspec spec

Cover photo by Ozzy Delaney on Flickr with creative commons license.

welaika