Getting accurate code coverage metrics from SimpleCov in a Rails project

June 18, 2015 | Ruby on Rails, Thoughts from the team

We use SimpleCov to track code coverage of our tests in Rails projects.  For coverage to be in any way useful as a metric it needs to be accurate.  We noticed that files for which we had no tests were not being tracked and not included in the coverage.  Therefore, our coverage metrics were artificially high and the reports that get generated did not include the 0% covered files so we had no idea tests were missing.

We went looking for a solution and found a code snippet in this issue that seemed to do what we wanted.  It made sure that all Ruby files were included in the coverage.  However, we soon noticed that the metrics were still wrong.  This time, lines that were covered by tests were being marked as uncovered.  In particular, it was lines 2..n of a multi-line statement e.g. a multi-line hash definition or a long ActiveRecord query.

We soon realised this was due to the naive way that the code we were using to force-load all files was going about it – reading a file line-by-line with no grammatical context.  We concluded that instead files needed to be loaded and interpreted to understand the meaning.  Thankfully, Rails gives us all the tools we need to achieve this painlessly (hat tip to Arkency).

First, you need to add Rails.application.eager_load! after SimpleCov.start in your test_helper.rb or spec_helper.rb file.  Then you need to make sure that all of the files you want to test are in your eager load path, so in application.rb add lines like the following:

config.eager_load_paths += %W(#{config.root}/lib)
config.eager_load_paths += Dir["#{config.root}/lib/**/"]

Now you can run your tests and discover your true code coverage.

More like this