Ruby on Rails, Io, Lisp, JavaScript, Dynamic Languages, Prototype-based programming and more...

Technoblog reader special: $10 off web hosting by FatCow!

Thursday, June 08, 2006

Prevent Yourself From Writing Bad Code

In an attempt to further train myself to constantly run unit tests, I have come up with a system that almost prevents me from checking in bad code into my Rails subversion repositories. It comes in two pieces.

First is RAILS_ROOT/lib/tasks/svn.rake:

desc "Checkin your changes after running the tests"
Rake::TestTask.new(:changed => [ :prepare_test_database ]) do |t|
info = `svn info`
since = Time.parse(info[/Last Changed Date: .*/])
touched = FileList['test/**/*_test.rb'].select { |path| File.mtime(path) > since } +
recent_tests('app/models/*.rb', 'test/unit', since) +
recent_tests('app/controllers/*.rb', 'test/functional', since)

t.libs << 'test'
t.verbose = true
t.test_files = touched.uniq

desc "Check-in work"
task :ci do
exec("rake", "setup_svn") if `which svnorig`[/no svnorig/]

tests = `rake changed`
puts tests
exec("svnorig", *YAML::load(ENV['MESSAGE'])) unless tests[/rake aborted/]

desc "Install subversion alias"
task :setup_svn do
svn = `which svn`.strip
exec("sudo mv #{svn} #{svn}orig && sudo ln -s #{File.expand_path(RAILS_ROOT)}/bin/svn #{svn} && echo 'All set, use svn ci as you normally would'")

Next is RAILS_ROOT/bin/svn:
#!/usr/bin/env ruby
require 'yaml'

if (ARGV[0] == "ci" || ARGV[0] == "commit") && File.exists?("lib/tasks/svn.rake")
ENV['MESSAGE'] = ARGV.to_yaml
exec("rake", "ci")
exec("svnorig", *ARGV)

To initialize this process, and you only have to do this once per machine you use it on, you simply type:
rake setup_svn

When prompted by sudo, type your user password and you are done.

Now, whenever you are in a Rails root directory and the file lib/tasks/svn.rake exists, svn ci does the following:

  • Find all files that you have touched since the last commit
  • Run and show the unit tests of all of those files
  • If the unit tests pass, commit the changes as expected
  • If the unit tests fail, exit

This all assumes that you have been good and wrote solid unit tests, but as the good programmer I know you are, that should be a valid assumption. Enjoy!

You should follow me on twitter here.

Technoblog reader special: click here to get $10 off web hosting by FatCow!


If you like this blog, you might also like top photography schools.