Class: Mutineer::Reporter
- Inherits:
-
Object
- Object
- Mutineer::Reporter
- Defined in:
- lib/mutineer/reporter.rb
Overview
Renders an AggregateResult: the summary block, mutation score, and per-file
survivor diffs. Stream discipline (R14): the report goes to out (stdout),
diagnostics/warnings go to err (stderr), so mutineer ... > report.txt
captures only the report.
source_map is { file_path => raw source string }, used to extract the
containing source line for each survivor diff.
Instance Method Summary collapse
-
#exit_code(threshold:) ⇒ Object
0 pass / 1 below threshold or untestable-with-errors.
-
#human_report(out, err, threshold) ⇒ void
Renders the human report.
-
#initialize(aggregate, source_map) ⇒ Reporter
constructor
A new instance of Reporter.
-
#report(out: $stdout, err: $stderr, threshold: 0.0, format: "human", output: nil, baseline: nil) ⇒ Object
Single entry point (R20/R21).
Constructor Details
#initialize(aggregate, source_map) ⇒ Reporter
Returns a new instance of Reporter.
17 18 19 20 |
# File 'lib/mutineer/reporter.rb', line 17 def initialize(aggregate, source_map) @agg = aggregate @source_map = source_map end |
Instance Method Details
#exit_code(threshold:) ⇒ Object
0 pass / 1 below threshold or untestable-with-errors. Usage errors (exit 2) are the CLI's job. When the score is nil (nothing killed or survived), pure no_coverage / all-ignored / empty still skip the gate; if any mutant was errored, timed out, or uncapturable, fail the gate so a broken harness cannot green CI under --threshold.
77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/mutineer/reporter.rb', line 77 def exit_code(threshold:) return 0 if threshold.nil? || threshold <= 0 score = @agg.mutation_score if score.nil? broken = @agg.errored_count + @agg.timeout_count + @agg.uncapturable_count return 1 if @agg.total.positive? && broken.positive? return 0 # pure no_coverage / ignored / empty — gate skipped end score >= threshold ? 0 : 1 end |
#human_report(out, err, threshold) ⇒ void
This method returns an undefined value.
Renders the human report.
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/mutineer/reporter.rb', line 53 def human_report(out, err, threshold) if @agg.total.zero? err.puts "No mutations generated — verify target files contain in-scope " \ "operators and are reached by the suite." return end out.puts "Mutineer — Mutation Results" out.puts "=========================" out.puts summary(out) out.puts score_line(out, err) per_source(out) survivors(out) verdict(out, threshold) if threshold && threshold.positive? end |
#report(out: $stdout, err: $stderr, threshold: 0.0, format: "human", output: nil, baseline: nil) ⇒ Object
Single entry point (R20/R21). Branches on format ("human" | "json") and
routes the rendered report to output (a file, with a stderr confirmation)
or to out. Diagnostics always go to err.
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/mutineer/reporter.rb', line 25 def report(out: $stdout, err: $stderr, threshold: 0.0, format: "human", output: nil, baseline: nil) rendered = if format == "json" json_report(baseline) elsif format == "html" html_report else sio = StringIO.new human_report(sio, err, threshold) baseline_section(sio, baseline) if baseline sio.string end if output abs = File.(output) File.write(abs, rendered) err.puts "Report written to #{abs}" else out.print rendered end end |