Skip to content

Add richer metrics to JSON formatter#1164

Merged
sferik merged 8 commits intomainfrom
json-formatter-metrics
Apr 17, 2026
Merged

Add richer metrics to JSON formatter#1164
sferik merged 8 commits intomainfrom
json-formatter-metrics

Conversation

@sferik
Copy link
Copy Markdown
Collaborator

@sferik sferik commented Apr 4, 2026

Enhance the JSON coverage output with per-file coverage percentages, a total section with aggregate statistics, full group stats, and method coverage support.

Per-file output now includes covered_percent (always), and when enabled: branches_covered_percent and methods array with methods_covered_percent. The total and groups sections report full statistics (covered, missed, total, percent, strength) for each enabled coverage type (line, branch, method).

Breaking change: group stats change from { covered_percent: 80.0 } to the full stats shape with the key renamed to percent.

Based on the ideas in codeclimate-community/simplecov_json_formatter#12.

This comment was marked as resolved.

@sferik sferik force-pushed the json-formatter-metrics branch 2 times, most recently from 30e31e9 to 8931869 Compare April 4, 2026 17:47
@sferik sferik force-pushed the json-formatter-metrics branch 2 times, most recently from 94db9fa to 3ea2cf7 Compare April 7, 2026 02:35
@brynary
Copy link
Copy Markdown
Contributor

brynary commented Apr 14, 2026

@sferik I did a very quick review of this and one thing caught my eye... It appears as though the statistics summaries are constructed such that, definitionally, total = covered + missed.

In our data, we track a third state which is "omit", which is for blank lines and comments -- lines that cannot be covered. We then define coverage as covered / (covered + missed) (excluding blanks and comments

This is a major difference and I'm guessing this definition is not new to SimpleCov in this PR, so this is just an FYI of something that I thought I'd mention as you are on a 1.0 push.

Copy link
Copy Markdown
Collaborator

@PragTob PragTob left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking great to me, again thanks for all your work and dedication you've poured into this 🙌

My comments are all smaller and on an optional level so can also all safely be ignored.

Image

Comment thread lib/simplecov/formatter/json_formatter/result_hash_formatter.rb Outdated
Comment thread lib/simplecov/formatter/json_formatter/result_hash_formatter.rb Outdated
Comment thread lib/simplecov/formatter/json_formatter/result_hash_formatter.rb Outdated
Comment thread CHANGELOG.md Outdated
Comment thread CHANGELOG.md Outdated
Comment thread lib/simplecov/formatter/json_formatter/result_hash_formatter.rb Outdated
@sferik
Copy link
Copy Markdown
Collaborator Author

sferik commented Apr 16, 2026

@brynary I added an omitted field to JSON line stats in the latest commit. Please let me know what you think.

sferik and others added 8 commits April 16, 2026 17:38
Enhance the JSON coverage output with per-file coverage percentages, a
total section with aggregate statistics, full group stats, and method
coverage support.

Per-file output now includes covered_percent (always), and when enabled:
branches_covered_percent and methods array with methods_covered_percent.
The total and groups sections report full statistics (covered, missed,
total, percent, strength) for each enabled coverage type (line, branch,
method).

Breaking change: group stats change from { covered_percent: 80.0 } to
the full stats shape with the key renamed to percent.

Based on the ideas in codeclimate-community/simplecov_json_formatter#12.

Co-Authored-By: Tejas <tejas.shetty@mailbox.org>
Report all four types of coverage threshold violations in the JSON
formatter's errors object: minimum_coverage, minimum_coverage_by_file,
minimum_coverage_by_group, and maximum_coverage_drop. Each violation
includes expected and actual values. This makes the JSON self-contained
for downstream consumers (e.g. CI reporters) that don't have access to
the Ruby process.

Co-Authored-By: Tejas <tejas.shetty@mailbox.org>
Expose the count of blank/comment lines (SimpleCov's `never_lines`) in
the line coverage statistics so downstream consumers can distinguish
lines that cannot be covered from lines that weren't covered.

Only line stats carry `omitted`; branches and methods have no
blank/comment analogue.
Build tooling, CI workflow changes, and a cucumber-feature fix aren't
relevant to consumers reading the changelog.
Match the rounding done in minimum_coverage_by_file,
minimum_coverage_by_group, and maximum_coverage_drop so the `actual`
value reported in errors is consistent across all thresholds.
Refactor the four error-formatting methods to use `if` guards instead
of `next unless ...` inside loops, extract the inner group loop to
`format_group_minimum_coverage_errors` to keep method length in
check, and disable RuboCop's `Style/Next` cop (which would otherwise
enforce the opposite style).
The four ExitCodes::*Check classes and the JSON formatter's
`errors` section each reimplemented the same logic: iterate
configured thresholds, fetch per-criterion actuals, round via
`SimpleCov.round_coverage`, and filter where `actual` fails the
threshold.

Centralize that in `SimpleCov::CoverageViolations` with four module
methods (`minimum_overall`, `minimum_by_file`, `minimum_by_group`,
`maximum_drop`). Each returns an array of canonical violation hashes
with consistent `:criterion`/`:expected`/`:actual` keys (plus
`:filename`/`:project_filename` or `:group_name`/`:maximum` as
appropriate).

Exit-code checks shrink to thin wrappers that render the violations;
the JSON formatter's four error-formatting methods collapse to a
single call + map each.
The HTML formatter's `build_stats` reimplemented CoverageStatistics
with different key names (`:pct` vs `percent`). Replace it by having
`coverage_summary` take a source_file and read from
`source_file.coverage_statistics`, and update `enabled_type_summary`
to call CoverageStatistics methods directly.

Source file ERB template simplifies from hand-building a
per-criterion counts hash to a single argument pass-through.
@sferik sferik force-pushed the json-formatter-metrics branch from fc1b562 to 4916a99 Compare April 17, 2026 00:42
@sferik sferik merged commit 51ad2bd into main Apr 17, 2026
24 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants