class SimpleCov::Formatter::Base
override ‘message_prefix` (e.g. JSON prepends “JSON ”).
Subclasses override `format` to do their actual writing, and may
to Y“ summary on stderr (it’s a status message, not data).
an output directory and emit a ”Coverage report generated for X
Shared scaffolding for formatters that write a coverage report to
@api private
def displayable_output_path
stay absolute; a `../../../tmp/cov` display would be more
instead of the bare directory `coverage`. Paths outside cwd
hyperlinks paths) can act on — e.g. `coverage/index.html`
points at a concrete file the user (or a terminal that
and appends the formatter's `entry_point_filename` so the line
inside cwd (e.g. `coverage` instead of `/Users/me/proj/coverage`)
status line. Renders relative to cwd when `output_path` lives
The path shown in the "Coverage report generated for X to Y"
def displayable_output_path directory = relative_or_absolute_output_path entry_point = entry_point_filename entry_point ? File.join(directory, entry_point) : directory end
def entry_point_filename
leaves the bare directory in place for any third-party formatter
gets appended to the directory in the status line. Default nil
(e.g. `index.html` for HTML, `coverage.json` for JSON), which
Subclasses override to name the report's entry-point file
def entry_point_filename nil end
def initialize(silent: false, output_dir: nil)
somewhere else (handy for tests that don't want to clobber the
pipeline keeps working unchanged. Pass it explicitly to write
`output_dir` defaults to `SimpleCov.coverage_path` so the at_exit
def initialize(silent: false, output_dir: nil) @silent = silent @output_dir = output_dir end
def message_prefix
summary line. Default empty for the HTML formatter, which has
Subclasses override to prepend a marker (e.g. "JSON ") to the
def message_prefix "" end
def output_message(result)
insertion order as `SourceFile#coverage_statistics`, which in
order of `result.coverage_statistics` (which is the same
to Y") is always first; per-criterion lines follow in the
measured. The header line ("Coverage report generated for X
Emit one summary line per criterion that the run actually
def output_message(result) header = "#{message_prefix}Coverage report generated for #{result.command_name} to #{displayable_output_path}" body = result.coverage_statistics.filter_map { |criterion, stat| stats_line(criterion, stat) } [header, *body].join("\n") end
def output_path
def output_path @output_dir || SimpleCov.coverage_path end
def relative_or_absolute_output_path
def relative_or_absolute_output_path absolute = output_path relative = Pathname.new(absolute).relative_path_from(Pathname.pwd).to_s relative.start_with?("..") ? absolute : relative rescue ArgumentError # Pathname#relative_path_from raises across mixed absolute/ # relative inputs (and across Windows drives) — keep the # absolute form on any unresolvable case. output_path end
def stats_line(criterion, stat)
Showing "Branch coverage: 0 / 0 (100.00%)" is noise; the older
measure (e.g. a file with no branches under branch coverage).
Returns nil for branch/method criteria that have nothing to
def stats_line(criterion, stat) return if criterion != :line && !stat.total.positive? percent = SimpleCov.round_coverage(stat.percent) Kernel.format( "%<label>s coverage: %<covered>d / %<total>d (%<percent>s)", label: criterion.to_s.capitalize, covered: stat.covered, total: stat.total, percent: SimpleCov::Color.colorize_percent(percent) ) end