eigenclass logo
Create  Edit  Diff  MAIN  Index  Search  Changes  History  PageRank  Login

rcov FAQ

Feel free to add your questions by editing this page.

Where can I get rcov?

The tarballs can be obtained from rcov: code coverage for Ruby or rubyforge.

rcov is also available in RubyGems? format:

gem install rcov

rcov is included in a number of distributions; as of 2006/08/11, it's available in

  • FreeBSD
  • Gentoo
  • Debian
  • ...

Why does rcov only support line (C0) coverage?

More precise analyses are difficult/impossible in the current implementation of Ruby. The abstract syntax tree doesn't hold enough information for accurate line coverage (rcov uses a number of heuristics to overcome this), let alone statement, branch and patch coverage...

Where can I report bugs?

For the time being, you can email your reports to mfp@acm.org (please include "rcov" in the subject to bypass the spam filters), or post them in the page holding the release notes and bug reports. You'll find a link to it in rcov: code coverage for Ruby.

How can I make rcov merge information from multiple runs of compiler.rb ?

You can use the --aggregate option, which was added in 0.7.0. Essentially, you just have to run your program using rcov with the --aggregate FILE option:

rm -f coverage.data
rcov -t --no-html --aggregate coverage.data file1.rb -- -args --to --file1.rb 
...
rcov --aggregate coverage.data fileN.rb -- -some --other --args foo.src

You can skip HTML report generation in all but the last run with --no-html; the -t (text summary) option stops rcov from complaining about the lack of files to analyze.

Note that --aggregate is fairly slow since all the execution count and coverage information must be saved in the specified file, as well as the code that was loaded (since in a later execution different files could be loaded/parsed).

How can I use rcov from an already running Ruby program?

I'm running a Ruby interpreter that is embedded within a C program. This situation is the inverse of how rcov is presently used: rcov is used to run *.rb files instead of ruby.

So, I want to be able to write something like "require 'rcov/runner'" and have rcov do it do its thing on the currently running Ruby program. This is like running unit tests by simply doing "require 'test/unit'" (which has a Kernel#at_exit statement that runs all the tests before the program terminates).

Thanks for your consideration.

You can use Rcov's API to analyze the code you want. In the case you describe, rcov/runner.rb would look like this:

require 'rcov'
require 'rbconfig'

# try to load xx, but don't give up if it's not available
begin
  require 'xx'
rescue LoadError
end
begin
  require 'rcov/report'
rescue NameError
  # hack to make textual reports work in the absence of xx-0.1.0
  # Rcov::HTMLCoverage cannot be used without it though
end

rcov_analyzer = Rcov::CodeCoverageAnalyzer.new
at_exit do
  rcov_analyzer.remove_hook
  rcov_analyzer.dump_coverage_info([Rcov::TextReport.new]) 
  # use Rcov::HTMLCoverage above to generate HTML reports; the formatters admit
  # a number of options, listed in rcov's RDoc documentation.
end
rcov_analyzer.install_hook

If you save that as rcov/runner.rb in your $LOAD_PATH, you will be able to

$ cat a.rb 

srand(0)
c = 0
d = 1
10.times do |i|
  if rand % (i + 10)
    c += i
    d += 1
  end
end
puts "blergh"
if c > 4*d
  # stuff
  puts "yep"
else
  puts "nope"
  # more stuff
end

puts "Done: #{c+d}"
$ ruby -I ../head/lib -rrcov/runner  a.rb 
blergh
yep
Done: 56
+----------------------------------------------------+-------+-------+--------+
|                  File                              | Lines |  LOC  |  COV   |
+----------------------------------------------------+-------+-------+--------+
|a.rb                                                |    20 |    16 |  81.2% |
+----------------------------------------------------+-------+-------+--------+
|Total                                               |    20 |    16 |  81.2% |
+----------------------------------------------------+-------+-------+--------+
81.2%   1 file(s)   20 Lines   16 LOC

How can I run all rails tests, like in the example?

I'm used to using "rake test" but rcov doesn't seem to like that. How can I run all functional, unit, and integration tests, as in your example?

Here's how you'd define coverage tasks for unit, functional and integration tests under the test:coverage namespace, as well as a test:coverage task that runs them all and yields an aggregate coverage rate:

require 'rcov/rcovtask'

namespace :test do 
  namespace :coverage do
    desc "Delete aggregate coverage data."
    task(:clean) { rm_f "coverage.data" }
  end
  desc 'Aggregate code coverage for unit, functional and integration tests'
  task :coverage => "test:coverage:clean"
  %w[unit functional integration].each do |target|
    namespace :coverage do
      Rcov::RcovTask.new(target) do |t|
        t.libs << "test"
        t.test_files = FileList["test/#{target}/*_test.rb"]
        t.output_dir = "test/coverage/#{target}"
        t.verbose = true
        t.rcov_opts << '--rails --aggregate coverage.data'
      end
    end
    task :coverage => "test:coverage:#{target}"
  end
end

This runs the unit, functional and integration tests separately (in different processes), aggregating the codde coverage data as it goes.

In general, Rails' tests must be run in separate processes (this is what "rake test" does too); you might get strange failures otherwise.

Note: In the above code, replace the line that looks like this: "test/#{target}/*_test.rb" with this: "test/#{target}/**/*_test.rb" to run tests in subdirectories like the default Rake tasks do. The wiki doesn't have the above code inline, so I can't change it myself.

--aggregate introduces some overhead, because quite a lot of information needs to be saved across runs (code coverage and execution count statistics, source code --- each test can require different files ---, etc).

How do I summarise rcov output across multiple projects?

See this page for a script that aggregates the results across several projects.

How can I list files that aren't covered at all?

You have to make sure that those files are required somewhere in your program (otherwise there's no way rcov could know about them). Just add

 require 'foo'

to some test file, or create a dummy test:

 $ cat > test/test_foo.rb
 require 'test/unit'
 require 'foo'
  
 ^D

Your question here