grodowski / undercover

undercover warns about methods, classes and blocks that were changed without tests, to help you easily find untested code and reduce the number of bugs. It does so by analysing data from git diffs, code structure and SimpleCov coverage reports

Home Page:https://undercover-ci.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Branch coverage fail with if...else conditions

GCorbel opened this issue · comments

I wrote this simple code :

class MyFile
  attr_accessor :body

  def my_method
    if body.present?
      puts 'ok'
    else
      puts 'yo'
    end
  end
end

And this spec :

require 'spec_helper'

describe MyFile do
  describe '#my_method' do
    it 'works' do
      my_file = MyFile.new
      my_file.body = ''
      my_file.my_method
      my_file.body = 'test'
      my_file.my_method
    end
  end
end

When I run this spec, this lcov file is generated :

SF:./lib/my_file.rb
DA:1,1
DA:2,1
DA:4,1
DA:5,2
DA:6,1
DA:8,1
BRDA:5,0,1,1
BRDA:7,0,2,1
BRF:2
BRH:2
end_of_record

Visualy, we can see every lines and branches are covered but when I run undercover -c origin/master -l coverage/lcov/lib-my_file.rb.lcov I have this output :

undercover: some methods have no test coverage! Please add specs for methods listed below

🚨 1) node `my_method` type: instance method,
      loc: lib/my_file.rb:4:10, coverage: 100.0%
 4:   def my_method hits: n/a
 5:     if body.present? hits: 2 branches: 1/1
 6:       puts 'ok' hits: 1
 7:     else hits: n/a
 8:       puts 'yo' hits: 1
 9:     end hits: n/a
10:   end hits: n/a

It seems everything is covered so I'm not supposed to have the "some methods have no test coverage" message.

Here is my spec_helper :

require 'simplecov'
require 'simplecov-lcov'

SimpleCov.formatter = SimpleCov::Formatter::LcovFormatter
SimpleCov.start do
  enable_coverage :branch
end

require 'undercover'

require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'

Report generated with simplecov-html show 100% coverage and no error on this file.

I have the success message with this code :

class MyFile
  attr_accessor :body

  def my_method
    body.present? ? puts('ok') : puts('yo')
  end
end

I think I spotted the issue. It comes from the Undercover::Result#uncovered? method :

def uncovered?(line_no)
coverage.each do |ln, _block, _branch, cov|
return true if ln == line_no && cov && cov.zero?
end
line_cov = coverage.find { |ln, _cov| ln == line_no }
line_cov && line_cov[1].zero?
end

Here, when I pass 7 as line_no coverage.find { |ln, _cov| ln == line_no } gives [7, 0, 2, 1], on next line line_cov[1].zero? gives true but the second position of the array is not for coverage but the block number. I guess change the last line by line_cov && line_cov.last.zero? will fix the issue.