Module: SimpleCov::CLI::Uncovered
- Defined in:
- lib/simplecov/cli/uncovered.rb
Overview
‘simplecov uncovered [–threshold N] [–top N] [–criterion C]` — list the lowest-coverage files (by the chosen criterion, ascending), so a developer can answer “where should I add tests next?” without opening a browser. Reads coverage.json directly.
Constant Summary collapse
- DEFAULT_TOP =
10- CRITERION_KEYS =
The coverage.json fields backing each criterion.
{ line: {percent: "lines_covered_percent", covered: "covered_lines", total: "total_lines"}, branch: {percent: "branches_covered_percent", covered: "covered_branches", total: "total_branches"}, method: {percent: "methods_covered_percent", covered: "covered_methods", total: "total_methods"} }.freeze
Class Method Summary collapse
-
.build_parser(opts) ⇒ Object
Option parsing with per-flag coercions is inherently ABC-heavy; the metric is noise here.
- .emit(stdout, files, opts) ⇒ Object
- .emit_json(stdout, files) ⇒ Object
- .emit_text(stdout, files, color) ⇒ Object
- .empty_message(json) ⇒ Object
- .format_row(fname, pct, covered, total, color) ⇒ Object
- .parse(args) ⇒ Object
- .rank(coverage_hash, threshold, keys) ⇒ Object
- .report(opts, keys, stdout, stderr) ⇒ Object
- .row_for(fname, payload, threshold, keys) ⇒ Object
- .run(args, stdout:, stderr:) ⇒ Object
- .unknown_criterion(criterion, stderr) ⇒ Object
Class Method Details
.build_parser(opts) ⇒ Object
Option parsing with per-flag coercions is inherently ABC-heavy; the metric is noise here.
60 61 62 63 64 65 66 67 68 69 |
# File 'lib/simplecov/cli/uncovered.rb', line 60 def build_parser(opts) # rubocop:disable Metrics/AbcSize OptionParser.new do |o| o.on("--input PATH") { |v| opts[:input] = v } o.on("--threshold N", Float) { |v| opts[:threshold] = v } o.on("--top N", Integer) { |v| opts[:top] = v } o.on("--criterion C") { |v| opts[:criterion] = v.to_sym } o.on("--json") { opts[:json] = true } o.on("--no-color") { opts[:no_color] = true } end end |
.emit(stdout, files, opts) ⇒ Object
48 49 50 |
# File 'lib/simplecov/cli/uncovered.rb', line 48 def emit(stdout, files, opts) opts[:json] ? emit_json(stdout, files) : emit_text(stdout, files, SimpleCov::CLI.color_enabled?(opts, stdout)) end |
.emit_json(stdout, files) ⇒ Object
75 76 77 78 79 80 |
# File 'lib/simplecov/cli/uncovered.rb', line 75 def emit_json(stdout, files) rows = files.map do |fname, pct, covered, total| {"file" => fname, "percent" => pct, "covered" => covered, "total" => total} end stdout.puts(JSON.pretty_generate(rows)) end |
.emit_text(stdout, files, color) ⇒ Object
71 72 73 |
# File 'lib/simplecov/cli/uncovered.rb', line 71 def emit_text(stdout, files, color) files.each { |fname, pct, covered, total| stdout.puts(format_row(fname, pct, covered, total, color)) } end |
.empty_message(json) ⇒ Object
82 83 84 |
# File 'lib/simplecov/cli/uncovered.rb', line 82 def (json) json ? "[]" : "simplecov uncovered: nothing to report" end |
.format_row(fname, pct, covered, total, color) ⇒ Object
100 101 102 103 104 |
# File 'lib/simplecov/cli/uncovered.rb', line 100 def format_row(fname, pct, covered, total, color) format("%<pct>s %<covered>d/%<total>d %<fname>s", pct: SimpleCov::Color.colorize_percent(pct, format("%6.2f%%", pct), enabled: color), covered: covered, total: total, fname: fname) end |
.parse(args) ⇒ Object
52 53 54 55 56 |
# File 'lib/simplecov/cli/uncovered.rb', line 52 def parse(args) opts = {input: SimpleCov::CLI.default_input, threshold: 100.0, top: DEFAULT_TOP, criterion: :line, no_color: false} build_parser(opts).parse(args) opts end |
.rank(coverage_hash, threshold, keys) ⇒ Object
86 87 88 89 |
# File 'lib/simplecov/cli/uncovered.rb', line 86 def rank(coverage_hash, threshold, keys) rows = coverage_hash.filter_map { |fname, payload| row_for(fname, payload, threshold, keys) } rows.sort_by { |_fname, pct, _c, _t| pct } end |
.report(opts, keys, stdout, stderr) ⇒ Object
33 34 35 36 37 38 39 40 41 |
# File 'lib/simplecov/cli/uncovered.rb', line 33 def report(opts, keys, stdout, stderr) return 1 unless (data = Report.load_data(opts[:input], stderr)) files = rank(data.fetch("coverage", {}), opts[:threshold], keys).first(opts[:top]) return stdout.puts((opts[:json])) || 0 if files.empty? emit(stdout, files, opts) 0 end |
.row_for(fname, payload, threshold, keys) ⇒ Object
91 92 93 94 95 96 97 98 |
# File 'lib/simplecov/cli/uncovered.rb', line 91 def row_for(fname, payload, threshold, keys) return unless payload.is_a?(Hash) && payload[keys[:total]].to_i.positive? pct = payload[keys[:percent]].to_f return if pct >= threshold [fname, pct, payload[keys[:covered]].to_i, payload[keys[:total]].to_i] end |
.run(args, stdout:, stderr:) ⇒ Object
25 26 27 28 29 30 31 |
# File 'lib/simplecov/cli/uncovered.rb', line 25 def run(args, stdout:, stderr:, **) opts = parse(args) keys = CRITERION_KEYS[opts[:criterion]] return unknown_criterion(opts[:criterion], stderr) unless keys report(opts, keys, stdout, stderr) end |
.unknown_criterion(criterion, stderr) ⇒ Object
43 44 45 46 |
# File 'lib/simplecov/cli/uncovered.rb', line 43 def unknown_criterion(criterion, stderr) stderr.puts("simplecov uncovered: unknown --criterion #{criterion.inspect} (expected line, branch, or method)") 1 end |