asplake

Wednesday, January 04, 2006

Test coverage with rcov and rake (96.2% at first attempt)

Last night I installed the rcoverage gem (recommended in Agile Web Development with Rails - there I go again!), only to discover in its README that its author recommends a switch to rcov.

Neither tool seems to be (shall we say) over-documented, but I did find Ruby On Rails Test Coverage in Alex Pooley's blog. I followed his instructions and soon had a report on one of my unit tests up and running.

As you may guess from Alex's article, rcov doesn't allow you to specify multiple test programs to run, so you need to maintain a script that will run the whole suite for you.

All that's needed is to require each test script, but I'm far too lazy (not to mention error-prone) to maintain lists of tests manually. Instead, here are three scripts I placed in my tests/ directory, to run unit tests, functional tests and both together.

test/unit_tests.rb:

  # Run all unit tests
    Dir[File.dirname(__FILE__) + "/unit/*_test.rb"].each do |f|
    require f
  end

test/functional_tests.rb:

  # Run all functional tests
  Dir[File.dirname(__FILE__) + "/functional/*_test.rb"].each do |f|
    require f
  end

test/all_tests.rb:

  # Combine unit and functional tests in one run
  %w( unit_tests functional_tests ).each do |f|
    require File.dirname(__FILE__) + "/#{f}.rb"
  end

Finally, I added the following to my project's Rakefile:

  # output directory - removed with "rake clobber" (needs a "require 'rake/clean'" above)
  CLOBBER.include("coverage")

  # RCOV command, run as though from the commandline.  Amend as required or perhaps move to config/environment.rb?
  RCOV = "/ruby/bin/ruby /ruby/bin/rcov"

  desc "generate a unit test coverage report in coverage/unit; see coverage/unit/index.html afterwards"
  task :coverage_units do
    sh "#{RCOV} --output coverage/unit test/unit_tests.rb"
  end

  desc "generate a functional test coverage report in coverage/functional; see coverage/functional/index.html afterwards"
  task :coverage_functional do
    sh "#{RCOV} --output coverage/functional test/functional_tests.rb"
  end

  desc "generate a coverage report for unit and functional tests together in coverage/all; see coverage/all/index.html afterwards"
  task :coverage_all do
    sh "#{RCOV} --output coverage/all test/all_tests.rb"
  end

  desc "equivalent to coverage_all"
  task :coverage => [:coverage_all]

The "desc" lines result in helpful output if I run "rake --tasks". I can never remember them all!

Running the overall coverage report is now as easy as "rake coverage", viewed by pointing my browser at coverage/all/index.html.

For the record, without changing any of my tests, I get an overall coverage rate of 96.2%, which came as quite a pleasant surprise.

One final word of warning: expect tests to run something like 2 orders of magnitude slower when running under rcov. Mine took nearly 5 minutes...

Technorati tags:

0 Comments:

Post a Comment

<< Home