FOSCON was great again this year. I gave a short speech on the shortcuts and aliases I use (download). I also stumbled onto a feature of rake that surprised even Jim Weirich.
If you define a rule with an empty string, you can catch any task that hasn’t been defined elsewhere. This makes it easy to dynamically create rake tasks. Essentially, this is method_missing for rake!
rule "" do |t| t.name # ... do something with the name of the task end
I experimented by writing a rule that will take a task with the format of controllername_testname and automatically run a single test from the relevant functional or unit test.
##
# Run a single test in Rails.
#
# rake blogs_list
# => Runs test_list for BlogsController (functional test)
#
# rake blog_create
# => Runs test_create for BlogTest (unit test)
rule "" do |t|
if /(.*)_([^.]+)$/.match(t.name)
file_name = $1
test_name = $2
if File.exist?("test/unit/#{file_name}_test.rb")
file_name = "unit/#{file_name}_test.rb"
elsif File.exist?("test/functional/#{file_name}_controller_test.rb")
file_name = "functional/#{file_name}_controller_test.rb"
else
raise "No file found for #{file_name}"
end
sh "ruby -Ilib:test test/#{file_name} -n /^test_#{test_name}/"
end
end
The possibilites are endless!

Now we’ll need official chain support, so plugins can happily use this feature together. Something like adding “super”, for overridden methods.
Thanks for posting these, I’ll definitely be applying some of the shell stuff at work. If you’re interested in automating some subversion stuff, check out my svn_tools plugin – it handles all the bootstrapping of a new rails project, among other stuff.
That’s pretty sweet. For what it’s worth, do check out my modified version of the above that gives you stuff like rake test:blog:create and rake test:blogs_controller.
Thanx for the shortcuts, they were pretty easy and time saving!! I m surely gonna apply some of this stuff at work. That’s sweet of you! :-)
This may sound like a newby question, but where / how do i use these shortcuts?
Thanks!
@Mike: Put it anywhere in a Rakefile at the root of your project.
The RailsEnvy guys also have a great tutorial on Rake:
http://railsenvy.com/2007/6/11/ruby-on-rails-rake-tutorial
Thanks for this, just what I wanted.
I improved it a bit to resolve clashes between unit test names and functional test names (I have both expense_claim_test.rb and expense_claim_controller_test.rb – just what scaffold gave).
Here’s my quick and ugly version:## # Run a single test in Rails. # # rake blogs_list # => Runs test_list for BlogsController (functional test; 'rake f_blogs_list' to force it if unit test found) # # rake blog_create # => Runs test_create for BlogTest (unit test; ('rake u_blog_create' to force it if functional test found)) rule "" do |t| if /(f_|u_|)(.*)_([^.]+)$/.match(t.name) flag = $1 force_functional = (flag == "f_") force_unit = (flag == "u_") file_name = $2 test_name = $3 if (force_unit || File.exist?("test/unit/#{file_name}_test.rb")) file_path = "unit/#{file_name}_test.rb" end if (force_functional || File.exist?("test/functional/#{file_name}_controller_test.rb")) file_path = "functional/#{file_name}_controller_test.rb" end if (!File.exist?("test/#{file_path}")) raise "No file found for #{file_path}" end sh "ruby -Ilib:test test/#{file_path} -n /^test_#{test_name}/" end endAnother link for newbies like me: Rake User Guide, http://docs.rubyrake.org/export/html/2
Found info on rules there. Server is currently down but google cache helps.
Thanks for this, just what I wanted.
I improved it a bit to resolve clashes between unit test names and functional test names (I have both expense_claim_test.rb and expense_claim_controller_test.rb – just what scaffold gave). Here’s my quick and ugly version:## # Run a single test in Rails. # # rake blogs_list (or f_blogs_list) # => Runs test_list for BlogsController (functional test; use f_blogs_list to force it if unit test found) # # rake blog_create (or u_blog_create) # => Runs test_create for BlogTest (unit test; use u_blog_create to force it if functional test found)) rule "" do |t| if /(f_|u_|)(.*)_([^.]+)$/.match(t.name) flag = $1 force_functional = (flag == "f_") force_unit = (flag == "u_") file_name = $2 test_name = $3 if (force_unit || File.exist?("test/unit/#{file_name}_test.rb")) file_path = "unit/#{file_name}_test.rb" end if (force_functional || File.exist?("test/functional/#{file_name}_controller_test.rb")) file_path = "functional/#{file_name}_controller_test.rb" end if (!File.exist?("test/#{file_path}")) raise "No file found for #{file_path}" end sh "ruby -Ilib:test test/#{file_path} -n /^test_#{test_name}/" end endhttp://pragmatig.wordpress.com/2008/03/19/testing-a-single-example-spec-testcase-test/
- same syntax, controllers -> test:blog_C (if both are named the same) - searches for matching files in unit/functional/integration - works with rspec too rake spec:blog:create
addition: rake spec:x -> first test matching x*_spec.rb, search in order model/controller/view/helper/any folder