About 90% of my development is done on Redmine and well over half of that is done on Redmine plugins. That means that I write tests; a lot of tests. Over time though, they get slower and slower and start to become a drain on productivity (“5 minutes to run the tests on a feature that took 30 seconds?!?!”).
The limiting factor is that Rails runs tests sequentially, so it only takes advantage of a single CPU core. I’ve started to use a great tool called parallel_tests to use all four cores but it hasn’t been working on tests for Rails plugins’ due to how it loads.
Until now…
With a bit of hacking, I’ve figured out how to load parallel_tests inside my plugin’s test suite. The setup was actually really simple:
- Setup parallel_tests just like in the Readme, but stop at step 4.
- Load the parallel_test rake file into your plugin (below)
- Run the tests
Loading parallel_tests
Just pop this into your plugin’s Rakefile (assuming you installed the plugin version of parallel_tests)
1 2 3 4 5 | parallel_tests = (File.join(File.dirname(__FILE__), '..', 'parallel_tests','lib','tasks','parallel_tests.rake')) if File.exists? parallel_tests RAILS_ROOT = File.dirname(__FILE__) import parallel_tests end |
Using rake’s import statement, the parallel_tests.rake file gets loaded directly into the plugin’s Rakefile. This makes the rake parallel tasks available.
I also had to define RAILS_ROOT because I monkey around with it in my plugin. You may be able to remove it in your plugin.
Results
I set this up for my redmine_kanban plugin and it cut my test suite’s running time from 4 minutes down to 2 minutes 38 seconds, a savings of 1 minute 22 seconds. That’s a massive improvement when you start running the test suite 10, 20, or 50 times a day.
$ time rake (in /home/edavis/dev/redmine/redmine-core/vendor/plugins/redmine_kanban) /usr/bin/ruby1.8 -I"lib:test" "/usr/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake/rake_test_loader.rb" "test/unit/kanban_issue_test.rb" "test/unit/helpers/kanbans_helper_test.rb" "test/unit/issue_test.rb" "test/unit/sanity_test.rb" "test/unit/kanban_test.rb" * DEFERRED: #update_issue_attributes should return false if the issue didn't save. Loaded suite /usr/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake/rake_test_loader Started ................................................................................... Finished in 63.503572 seconds. 83 tests, 267 assertions, 0 failures, 0 errors /usr/bin/ruby1.8 -I"lib:test" "/usr/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake/rake_test_loader.rb" "test/functional/kanbans_controller_test.rb" Loaded suite /usr/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake/rake_test_loader Started ................................ Finished in 139.429962 seconds. 32 tests, 79 assertions, 0 failures, 0 errors /usr/bin/ruby1.8 -I"lib:test" "/usr/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake/rake_test_loader.rb" "test/integration/kanban_board_test.rb" Loaded suite /usr/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake/rake_test_loader Started .. Finished in 9.012205 seconds. 2 tests, 12 assertions, 0 failures, 0 errors real 3m59.730s user 3m32.413s sys 0m21.733s
$ time rake parallel:test (in /home/edavis/dev/redmine/redmine-core/vendor/plugins/redmine_kanban) /home/edavis/dev/redmine/redmine-core/vendor/plugins/parallel_tests/lib/tasks/../parallel_tests.rb:4: warning: already initialized constant VERSION 4 processes for 7 tests, ~ 1 tests per process Loaded suite -e Started . * DEFERRED: #update_issue_attributes should return false if the issue didn't save. Loaded suite -e Started .Loaded suite -e Started .Loaded suite -e Started ............................................. Finished in 14.261201 seconds. 31 tests, 56 assertions, 0 failures, 0 errors ... Finished in 14.744914 seconds. 14 tests, 43 assertions, 0 failures, 0 errors ........................................ Finished in 52.973448 seconds. 41 tests, 180 assertions, 0 failures, 0 errors ........................... Finished in 147.211034 seconds. 32 tests, 79 assertions, 0 failures, 0 errors Results: 41 tests, 180 assertions, 0 failures, 0 errors 14 tests, 43 assertions, 0 failures, 0 errors 31 tests, 56 assertions, 0 failures, 0 errors 32 tests, 79 assertions, 0 failures, 0 errors Took 156.279382 seconds real 2m38.223s user 0m1.600s sys 0m0.416s
Don’t settle for Rails only using one core, put your quad core behemoth back to work.
Eric Davis
No related posts.
