Global coverage numbers can hide the risk in the change you are reviewing.
A project can report a healthy overall coverage percentage while the current branch adds untested behavior.
The inverse is also true. A project with a weak historic baseline can still hold a high bar for new work.
That is why I like having a coverage view focused on files changed in the current branch.
The problem with one global number
Coverage is useful as a signal, but a single percentage is too blunt for day-to-day review. It says something about the repository, not necessarily about the pull request.
During review, the more useful question is narrower:
Did this change add behavior without tests?
SimpleCov already gives Ruby projects a good foundation. The missing piece is a group that only includes files changed against the reference branch.
A SimpleCov group for changed files
The setup is small: ask Git which Ruby files changed and group those files in the SimpleCov report.
require "pathname"
require "simplecov"
class ChangedRubyFiles
def self.include?(filename)
changed_files.include?(filename)
end
def self.changed_files
@changed_files ||= `git diff --name-only main`.split("\n").filter_map do |file|
path = Pathname.new(Rails.root.join(file))
path.to_s if path.extname == ".rb"
end
end
end
SimpleCov.start("rails") do
add_group "Current branch" do |source_file|
ChangedRubyFiles.include?(source_file.filename)
end
end
Use master instead of main if that is still the repository’s default branch.
How to use the signal
This should not become another vanity metric. It should make review sharper.
If a changed file appears in the group with poor coverage, the reviewer has a concrete place to look. If the missing lines are trivial, ignore them. If they are decision branches, failure paths, or permission checks, test them.
This also helps with legacy systems. You do not need to fix the entire repository before improving the discipline around new changes.
Caveats
This technique is intentionally small. It will not understand generated files, moved files, or every monorepo layout without adjustment. It also measures line execution, not test quality.
That is fine. The aim is not perfect coverage. The aim is to make the current branch harder to review lazily.
Addendum: SimpleCov and branch coverage today
SimpleCov can report branch coverage, but line coverage is still the default primary coverage type.
If you want branch coverage, enable it explicitly.
SimpleCov.start("rails") do
enable_coverage :branch
end
You can also make branch coverage the primary metric:
SimpleCov.start("rails") do
enable_coverage :branch
primary_coverage :branch
end
That changes what SimpleCov emphasizes, but it does not replace the branch-focused group from this note.
These are two different questions:
- branch coverage asks whether conditional paths were exercised.
- changed-file grouping asks whether the current branch added untested code.
In practice, the better setup is often both.
Enable branch coverage, then add a group for changed Ruby files so review stays focused on the code being changed.
Useful reference: SimpleCov coverage criteria and primary coverage.
