Friday, May 11, 2007

rcov for rails and how to analyze its reports

rcov is a code coverage tool for Ruby.

There are at least two reasons why it's worth using code coverage tools in your application.
1. It shows you which area of your code is untested.

This information can give you some clue, where it might be worth to cover the code with tests.

2. Gives you information about the code that is never executed.

You run your tests and the code coverage tool reveals a code that was not executed. It either means that this part was not tested or that the code is actually never used by your application. If it's the second case then you may simplify your codebase by removing the code. Don't worry, if you think you will later need it you can always find it your Subversion history. You use version control system, don't you?

rcov for Rails - installation

First, you install rcov gem.

gem install rcov

Then, you go to your application directory and install rcov for rails plugin:

./script/plugin install http://svn.codahale.com/rails_rcov

The plugin extends your Rake by adding new tasks like:

rake test:units:rcov
rake test:functionals:rcov

When you run 'rake test:units:rcov', it first runs all of your unit tests and then creates a coverage report. You can find it in the coverage/units directory.
It also outputs a simple text report:

5 tests, 13 assertions, 0 failures, 0 errors
+----------------------------------+-------+-------+--------+
| File | Lines | LOC | COV |
+----------------------------------+-------+-------+--------+
|app/controllers/application.rb | 7 | 3 | 100.0% |
|app/helpers/application_helper.rb | 3 | 2 | 100.0% |
|app/models/word.rb | 21 | 18 | 100.0% |
+----------------------------------+-------+-------+--------+
|Total | 31 | 23 | 100.0% |
+----------------------------------+-------+-------+--------+
100.0% 3 file(s) 31 Lines 23 LOC

How to analyze rcov results?

That's a result for the current code of our Words application. The only line that is interesting here is the one for word.rb. It says that the tests fully cover the Word class, which is a good thing.
When I run 'rake test:functionals:rcov' I get the following:

1 tests, 2 assertions, 0 failures, 0 errors
+-----------------------------------+-------+-------+--------+
| File | Lines | LOC | COV |
+-----------------------------------+-------+-------+--------+
|app/controllers/application.rb | 7 | 3 | 100.0% |
|app/controllers/words_controller.rb| 6 | 5 | 100.0% |
|app/helpers/application_helper.rb | 3 | 2 | 100.0% |
|app/helpers/words_helper.rb | 2 | 2 | 100.0% |
|app/models/word.rb | 21 | 18 | 22.2% |
+-----------------------------------+-------+-------+--------+
|Total | 39 | 30 | 53.3% |
+-----------------------------------+-------+-------+--------+

First, let's have a look at the second line, which says that we have 100% test coverage for the word_controller. That's nice. Have a look at the last line, related to the word.rb file. Why do we have only 22.2% here? Is that a problem? Does it mean that we have untested code? The answer is 'no'. We shouldn't be bothered about this line. Remember that test:functionals are tests for the controllers and this what we focus our tests on. We don't want to care about model classes here, they are already tested in test:units suite. In our case the reason for a low coverage is that we mock the Word.random method in our controller's tests. The real Word class is never called.

Summarizing, all we should care about in my opinion are results of coverage analysis for model classes when we run test:units and the results for controllers when we run test:functionals.
I suggest you give rcov a try. It should take you only 5 minutes to discover how your tests cover the code of the application. Who knows, maybe you can find some code that was never executed?

No comments: