Cutting RSpec Test Time: Continuous Integration ready rake task

Talking about RSpec test time once again….. This post is the continuation of Quick Hack: Cutting RSpec test time…

I had ended the last post with a crude rake task, which was good for visual analysis but was not ready for Continuous Integration servers(like CruiseControl). The task has improved(and is in-fact now easy to tune for better performance). The simple rule of thumb is, it should parallelize it in such a way, that all the processes(spec threads), should end as close to each other as possible.

Here is the new rake task http://pastie.org/269318. More we fork, more the number of databases, more the time wasted in rake db:schema:load. So the trick is to avoid overdoing it, and trying to get parallel processes ending as close to each other as possible, so that IO bound/blocked time for one, is compensated by others.

The other addition is, that the task now merges test results. The main process waits for children to end, and uses there return value to decide its own return value(which CruiseControl.rb consumes to decide success or failure). Line 52-57 are doing this trick.

So if you plan to use something similar, make your continuous integration server run rake spec:fast. For CruiseControl.rb it will boil down to CruiseControl::invoke_rake_task(‘spec:fast’). You do not need to do anything more in the cruise rake task(no environment override, no db:migrate… nothing).

How does it work???
Here is how it balances, check out the line number 21 in the pastie… 

1
2
{:models_test => :models, :controllers_test => :controllers,
  :lib_test => [:extensions, :initializers, :rspec_extensions, :lib, :views, :helpers]}

It is confugured to run 3 parallel processes, with environments(models_test, controllers_test and lib_test). There are close to 270 model and 280 controller specs in my project, and the rest(which are extensions, initializers, lib… etc) have got  close to 320 specs. So this distribution gave me an optimal test time cut, since the last process now ends within 20 seconds from the first.

WARNING: On a slow/ancient machine… like 1.6 GHz Pentium 4 with 1 GB of RAM, this may not show any effect at all…. You need a dual core box with good RAM and decent FSB freq to see this hack in action. On a 2 CPU machine, it will be even better…(The stats i posted on the last post, were from my MacBook Pro with Intel Core 2 Duo[2.4 GHz], 3 MB L2 cache, 2 GB RAM and 800 MHz Bus Speed running OSX Leopard). I used this little thing to test its effectiveness.


About this entry