First impressions of Ruby branch coverage with DeepCover

Branch coverage for Ruby is finally on the horizon! The built-in coverage library is expected to ship in Ruby 2.5 with branch and method coverage options.

And a pure-Ruby gem is in development, too: DeepCover.

I gave DeepCover a try with my main project, the Wiki Education Dashboard, and the coverage of the Ruby portions of the app dropped from 100% to 96.75%. Most of that is just one-line guard clauses like this:

return unless Features.wiki_ed?

But there are a few really useful things that DeepCover revealed. First off, unused scopes on Rails ActiveRecord models:

<br />
class Revision &lt; ActiveRecord::Base<br />
  scope :after_date, -&gt;(date) { where('date &gt; ?', date) }<br />
end<br />

Unlike default line coverage, DeepCover showed that this lambda wasn’t ever actually used. It was dead code that I removed today.

Similarly, DeepCover shows where default arguments in a method definition are never used, like this:

<br />
class Article &lt; ActiveRecord::Base<br />
  def update(data={}, save=true)<br />
    self.attributes = data<br />
    self.save if save<br />
  end<br />
end<br />

This method was overriding the ActiveRecord update method, adding an option to update without saving. But we no longer use that second argument anywhere in the codebase, meaning I could delete the whole method and rely on the standard version of update.

4 thoughts on “First impressions of Ruby branch coverage with DeepCover”

  1. DeepCover co-author here. Thanks for the great examples. The unused scope is probably fairly typical. You mention unused default arguments (which DeepCover can detect), but in the update case, I imagine that the default argument was always used (which we should detect) and that it’s actually DeepCover’s branch coverage that alerted you to the face that `if save` was always true, right?

    1. I think it’s that the default argument was always used, but it was detecting that nothing *except* the default argument was used. I’m not completely sure, though.

      The `def` line is the one that was marked as uncovered. (I did this via simplecov, so I didn’t get the visualization of the uncovered parts within the line.)

Leave a Reply

Your email address will not be published. Required fields are marked *