I’m generating test tasks dynamically based on existing test files in a Rakefile. Consider you have various unit test files named after the pattern test_<name>.rb. So what I’m doing is creating a task named after the file name inside the ‘test’ namespace.
With the code below I can then call all the tests with rake test:<name>
require 'rake/testtask'
task :default => 'test:all'
namespace :test do
desc "Run all tests"
Rake::TestTask.new(:all) do |t|
t.test_files = FileList['test_*.rb']
end
FileList['test_*.rb'].each do |task|
name = task.gsub(/test_|\.rb\z/, '')
desc "Run #{name} tests"
Rake::TestTask.new(:"#{name}") do |t|
t.pattern = task
end
end
end
The above code works, it just seems too much code for simple task generation.
And I still haven’t figured out a way to print some description text to the console like puts "Running #{name} tests:"
Is there a more elegant way than the above method?
EDIT: What I really expected to get was an alternative to the loop to define the tasks dynamically but I guess the rake lib doesn’t provide any helper to that so I’m stuck with the loop.
Here’s another way to solve the problem using rules in Rake.
A rake rule kicks in whenever rake wants to build “X”, and it finds a rules that says “to build X, use Y”. We will setup a rule that triggers when someone specifies a target in the format “test:XXX”, it will attempt to use a file named “test/test_XXX.rb”.
Suppose you have a test file named “test/test_my_code.rb”. To execute that test file, just type:
The rule is triggered whenever there is a target beginning with “test:” that cannot matched by any other task. It then looks for a file given by the lamdba function. The lambda transforms the target name “test:XXX” into a filename “test/test_XXX.rb”. If the filename exists, the body of the rule is executed.
The body of the rule just runs the test file as an executable. This is generally enough to run the tests of a single file. If you need to add library paths (e.g. “lib”) to the load path for the tests, you can change the rule body to be something like
Another difference between this and the explicit loop solution is that rake will not print out descriptions for rules, so the “rake -T” output won’t include the individual tests in its output.
I don’t know if this is better than the the original, but it does give you some options.