Rcov — measure your test coverage (Ruby on Rails)

Fact: Code can be developed that contains no bugs.
Fiction: That the above happens often.

The act of software development in itself is prone to many errors; typo’s, assigning one variable to another without remembering variable types, and more often adding features to existing software and not updating all of the calling code that now does not know it has to pass in a third method parameter.

To combat the unseen errors we can call rake commands to run our unit, functional, and integration tests. But if the tests are not up-to-par, for example they all assert true regardless of any actual testing, then in reality the results are meaningless. So, in essence, to combat poor test coverage, which tries to combat errors in feature development, I decided to give Rcov a try. I took my latest RoR project and built a rake task to run my unit, functional, and integration tests through Rcov. At first I was rather upset when I saw the Rcov results; I was pretty much being told I failed test writing class. On we go…

What is Rcov?
Rcov is a necessary tool if you want to write code that not only works but will also allow for expansion and adaptation (and there are other reasons as well, but that is for you to find out). Technically, it is a tool that measures your code coverage from your tests in a Ruby (and RoR) project. Taken from eigenclass.org, the maker of Rcov, the main points are presented as follows:
* fast execution: 20-300 times faster than previous tools
* multiple analysis modes: standard, bogo-profile, “intentional testing”, dependency analysis…
* detection of uncovered code introduced since the last run (“differential code coverage”)
* fairly accurate coverage information through code linkage inference using simple heuristics
* cross-referenced XHTML and several kinds of text reports
* support for easy automation with Rake and Rant
* colorblind-friendliness

Rcov in action

Rcov in action

With that all said, the point of this entry is to not only get other developers using Rcov, but to also share my rake task that I put compiled after reading a few blogs and looking at other Rcov rake task plugins and examples sources. My code was mainly adapted from Alan Johnson ( github plugin project page ).

Mileage may vary. I created a file called rcov.rake in my project/lib/tasks/ folder and its contents:

def run_coverage(files)
  rm_f "coverage"
  rm_f "coverage.data"
 
  # turn the files we want to run into a  string
  if files.length == 0
    puts "No files were specified for testing"
    return
  end
 
  files = files.join(" ")
 
  if PLATFORM =~ /darwin/
    exclude = '--exclude "gems/*"'
  else
    exclude = '--exclude "rubygems/*"'
  end
 
  rcov = "rcov --rails -Ilib:test --sort coverage --text-report #{exclude} --no-validator-links --aggregate coverage.data"
  cmd = "#{rcov} #{files}"
  sh cmd
end
 
namespace :test do
 
  desc "Measures unit, functional, and integration test coverage"
  task :coverage do
    run_coverage Dir["test/**/*.rb"]
  end
 
  namespace :coverage do
    desc "Runs coverage on unit tests"
    task :units do
      run_coverage Dir["test/unit/**/*.rb"]
    end
    desc "Runs coverage on functional tests"
    task :functionals do
      run_coverage Dir["test/functional/**/*.rb"]
    end
    desc "Runs coverage on integration tests"
    task :integration do
      run_coverage Dir["test/integration/**/*.rb"]
    end
  end
end

More information on Rcov is available from the links below:

eigenclass

RubyForge for Rcov

clarkware

Agile Web Development — Rcov