I have not really been getting into blogging yet, obviously. It’s been several months since the most recent post. I’m in New York at the moment, getting ready to launch a rails web project. More details about that later.
For now, I just had to post something I did recently that was handy: Using rake to run a specific group of files.
There are some great built-in tasks provided by Rake. Let’s look at the testing-related ones (run ‘rake -T’ to see them all):
rake test:functionals # Run the functional tests in test/functional rake test:integration # Run the integration tests in test/integration rake test:plugins # Run the plugin tests in vendor/plugins/*/**/test (or specify with PLUGIN=name) rake test:recent # Test recent changes rake test:uncommitted # Test changes since last checkin (only Subversion) rake test:units # Run the unit tests in test/unit
These are all very useful. But on the site I’m currently working on, I wanted to run a set of tests that were related to a section of the web site: the web store. I wanted to be able to run a specific combination of unit, functional, and integration tests.
I looked at the source for the tasks that rails provides for rake. The testing tasks are defined in lib/tasks/testing.rake in the rails distribution. The code for the unit testing task, for example:
desc "Run the unit tests in test/unit"
Rake::TestTask.new(:units => "db:test:prepare") do |t|
t.libs << "test"
t.pattern = 'test/unit/**/*_test.rb'
t.verbose = true
end
The files are specified as a glob. But, I did not want to use a file pattern. I consulted the rake API docs and discovered the test_files= setter method of Rake::TestTask. Here’s what I ended up with:
namespace :test do
tests = []
tests << "test/integration/store_test.rb"
# models
%w(product product_category product_categorization product_option product_option_value
line_item cart order shipment).each do |file|
tests << "test/unit/#{file}_test.rb"
end
# controllers
%w(cart checkout store).each do |file|
tests << "test/functional/#{file}_controller_test.rb"
end
# admin controllers
%w(products product_option_values product_options orders).each do |file|
tests << "test/functional/admin/#{file}_controller_test.rb"
end
Rake::TestTask.new(:store => "db:test:prepare") do |t|
t.libs << "test"
t.test_files = tests
t.verbose = true
end
Rake::Task['test:store'].comment = "Run the store-related tests"
end
I saved this task in lib/tasks/store_tests.rake under my project directory. Now, I can do this:
$ rake test:store (in ~/rails_project) /opt/local/bin/ruby -Ilib:test "/opt/local/lib/ruby/gems/1.8/gems/rake-0.7.1/lib/rake/rake_test_loader.rb" "test/integration/store_test.rb" "test/unit/product_test.rb" "test/unit/product_category_test.rb" "test/unit/product_categorization_test.rb" [... etc ...] Loaded suite /opt/local/lib/ruby/gems/1.8/gems/rake-0.7.1/lib/rake/rake_test_loader Started .................................................................... Finished in 10.799886 seconds. 68 tests, 682 assertions, 0 failures, 0 errors
All the store tests are run as a group. This is a nice way to verify that things are working in the money-making part of the site.
However, I have to remember to update the task whenever I refactor or make additions. I’m thinking about symbolic links, now. Perhaps the tests could be grouped together in a directory (like test/groups/store) by making symbolic links to them in there. And, subversion deals with symlinks well…



