For one of our Ruby projects, we split its test suite into several chunks, run them in parallel, and feed SonarQube with all partial code coverage reports. That, however, results in SonarQube incorrectly reporting non-executable lines of code (empty, end
s, etc.) as not covered.
This is caused by SonarQube incorrectly merging several SimpleCov reports. For example, for one of our classes, SimpleCov generates the report below (shortened for example purposes) for the test chunk that includes its tests:
"/w/some/file.rb": {
"lines": [
1,
2,
null,
1,
null,
null
]
},
test chunks that don’t include that class’ tests result in a report like
"/w/some/file.rb": {
"lines": [
0,
0,
0,
0,
0,
0
]
},
which SonarQube logic aggregates into
"/w/some/file.rb": {
"lines": [
1,
2,
0,
1,
0,
0
]
},
Resulting in 50% line coverage for a file, where the real coverage is 100%.
SimpleCov itself also includes aggregation logic, and that logic explicitly says that null
and 0
should be merged into null
: simplecov/lib/simplecov/combine/lines_combiner.rb:
# Return depends on coverage in a specific line
#
# @param [Integer || nil] first_val
# @param [Integer || nil] second_val
#
# Logic:
#
# => nil + 0 = nil
# => nil + nil = nil
# => int + int = int
#
# @return [Integer || nil]
I’m open to submit a fix for the logic, but would love for someone to confirm my findings first.
Related posts: