What’s more terrifying than being stabbed in the face with a spork? Being stabbed in the face with 2 sporks!
In these days where even laptops are dual or quad-core parallel_tests is a great tool for using all of those cores when running specs. Spork is another great tool for avoiding the overhead of loading rails, gems etc. when running tests.
Out of the box spork and parallel_tests don’t work together. When spork receives a request to run specs it aborts its current run, so only one of your parallel_spec instances actually gets to run. In addition parallel_spec’s trick of setting an environment variable to indicate which test environment should be used doesn’t work, because the runners forked by spork don’t inherit the environment parallel_spec sets up.
Fortunately there are at least two ways to get around this. I assume that you’ve already got parallel_tests up and running with the required extra databases, changes to database.yml etc.
Method 1: Multiple sporks
Grab the right version of parallel_tests
Make sure you’ve got parallel_tests 0.5 or later (Previous versions deal with the .opts file in a different way)
Gentlemen, start your sporks
Run as many sporks as you need. Run the first one on port 8989 (the default), the second on port 8991, the third on 8992 and so on. You should set TEST_ENV_NUMBER in each one, so your invocations should look like
1 2 3 |
|
and so on
Setup parallel_spec.opts
Edit spec/parallel_spec.opts so that it looks like
--drb --drb-port <%= 8989 + ENV['TEST_ENV_NUMBER'].to_i %> --format progress --format ParallelSpecs::SpecRuntimeLogger --out tmp/parallel_profile.log
Profit:
Run parallel_spec
. When rspec is invoked it passes the .opts file through erb so the first instance (TEST_ENV_NUMBER=‘’) will have –drb-port set to 8989, the second to 8991 and so on. Each rspec will connect to a different spork instance that has the correct TEST_ENV_NUMBER setup.
Method 2: Single hacked spork
A disadvantage to method 1 is that you have multiple instances of spork sitting around, consuming memory. It requires extra keystrokes to ensure each spork instance is restarted properly and more cpu cycles are consumed everytime you restart spork.
Use my spork
My fork of spork doesn’t prohibit running multiple spec runs concurrently and allows environment data parallel_tests requires to be passed in. I’ve only modified the forking strategy.
Setup script/spec
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
This ensures that when parallel_spec runs script/spec, the test environment number is passed through to the chikd
Make sure the right database is used
When spork forks a child with a specific TEST_ENV_NUMBER we need to ensure that the child connects to the correct database. This can be done with a Spork.each_run block in your spec_helper.rb. The app I’ve been working with uses mongomapper as well as Active Record, so my each_run block looks like this.
1 2 3 4 5 6 7 8 9 |
|
Profit
bundle exec spork
and run parallel_spec as normal (things won’t work if the ‘normal’ version of the spork binary is run). Your spork will fork multiple instances which will pick up TEST_ENV_NUMBER and reconfigure their database settings as needed.