Module: SimpleCov::CLI::Uncovered
Overview
simplecov uncovered: the lowest-coverage files by the chosen criterion,
ascending, so a developer can answer "where should I add tests next?"
without opening a browser.
Defined Under Namespace
Modules: Misses
Constant Summary
collapse
- DEFAULT_TOP =
10
CommandHelpers::STATS_ROW_FORMAT
Instance Method Summary
collapse
-
#build_row(fname, pct, payload, opts, keys) ⇒ Object
-
#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
-
#own_options(parser, options) ⇒ Object
-
#parse(args) ⇒ Object
-
#rank(coverage_hash, opts, keys) ⇒ Object
-
#report(opts, keys, stdout, stderr) ⇒ Object
-
#row_for(fname, payload, opts, keys) ⇒ Object
-
#run(args, stdout:, stderr:) ⇒ Object
-
#unknown_criterion(criterion, stderr) ⇒ Object
-
#validate_top(value) ⇒ Object
A negative count would raise from Array#first, so it is reported as the parse error it is.
build_parser, command_name, common_options, error, error_nil, on_help, one?, parse_common, quiet_option, recorded_contexts, stats_row
Instance Method Details
#build_row(fname, pct, payload, opts, keys) ⇒ Object
114
115
116
117
118
|
# File 'lib/simplecov/cli/uncovered.rb', line 114
def build_row(fname, pct, payload, opts, keys)
row = [fname, pct, payload[keys.fetch(:covered)].to_i, payload.fetch(keys.fetch(:total)).to_i]
row << Misses.missed_for(payload, opts.fetch(:criterion)) if opts.fetch(:missing)
row
end
|
#emit(stdout, files, opts) ⇒ Object
48
49
50
51
52
53
54
|
# File 'lib/simplecov/cli/uncovered.rb', line 48
def emit(stdout, files, opts)
kind = opts.fetch(:annotate)
return Misses.annotate(stdout, files, opts.fetch(:criterion), kind) if kind
return stdout.puts(empty_message(opts.fetch(:json))) if files.empty?
opts.fetch(:json) ? emit_json(stdout, files) : emit_text(stdout, files, CLI.color_enabled?(opts, stdout))
end
|
#emit_json(stdout, files) ⇒ Object
87
88
89
90
91
92
93
94
|
# File 'lib/simplecov/cli/uncovered.rb', line 87
def emit_json(stdout, files)
rows = files.map do |fname, pct, covered, total, missed|
row = {"file" => fname, "percent" => pct, "covered" => covered, "total" => total}
row["missing"] = missed if missed
row
end
stdout.puts(JSON.pretty_generate(rows))
end
|
#emit_text(stdout, files, color) ⇒ Object
79
80
81
82
83
84
85
|
# File 'lib/simplecov/cli/uncovered.rb', line 79
def emit_text(stdout, files, color)
files.each do |fname, pct, covered, total, missed|
row = format_row(fname, pct, covered, total, color)
row += " missing #{Patch::Output.ranges(missed, ",")}" if missed&.any?
stdout.puts(row)
end
end
|
#empty_message(json) ⇒ Object
96
97
98
|
# File 'lib/simplecov/cli/uncovered.rb', line 96
def empty_message(json)
json ? "[]" : "simplecov uncovered: nothing to report"
end
|
120
121
122
123
124
|
# File 'lib/simplecov/cli/uncovered.rb', line 120
def format_row(fname, pct, covered, total, color)
format("%<pct>s %<covered>d/%<total>d %<fname>s",
pct: Color.colorize_percent(pct, format("%6.2f%%", pct), enabled: color),
covered: covered, total: total, fname: fname)
end
|
#own_options(parser, options) ⇒ Object
62
63
64
65
66
67
68
|
# File 'lib/simplecov/cli/uncovered.rb', line 62
def own_options(parser, options)
parser.on("--threshold N", Float) { |v| options[:threshold] = v }
parser.on("--top N", Integer) { |v| options[:top] = validate_top(v) }
parser.on("--criterion C") { |v| options[:criterion] = v.to_sym }
parser.on("--missing") { options[:missing] = true }
parser.on("--annotate KIND") { |v| options[:annotate] = v }
end
|
#parse(args) ⇒ Object
56
57
58
59
60
|
# File 'lib/simplecov/cli/uncovered.rb', line 56
def parse(args)
opts, = parse_common(args, threshold: 100.0, top: DEFAULT_TOP, criterion: :line,
missing: false, annotate: nil) { |o, options| own_options(o, options) }
opts
end
|
#rank(coverage_hash, opts, keys) ⇒ Object
100
101
102
103
|
# File 'lib/simplecov/cli/uncovered.rb', line 100
def rank(coverage_hash, opts, keys)
rows = coverage_hash.filter_map { |fname, payload| row_for(fname, payload, opts, keys) }
rows.sort_by { |_fname, pct, _c, _t| pct }
end
|
#report(opts, keys, stdout, stderr) ⇒ Object
35
36
37
38
39
40
41
|
# File 'lib/simplecov/cli/uncovered.rb', line 35
def report(opts, keys, stdout, stderr)
coverage = CoverageFile.load_coverage(opts.fetch(:input), command: "uncovered", stderr: stderr)
return 1 unless coverage
emit(stdout, rank(coverage, opts, keys).first(opts.fetch(:top)), opts)
0
end
|
#row_for(fname, payload, opts, keys) ⇒ Object
105
106
107
108
109
110
111
112
|
# File 'lib/simplecov/cli/uncovered.rb', line 105
def row_for(fname, payload, opts, keys)
return unless payload.instance_of?(Hash) && payload[keys.fetch(:total)].to_i.positive?
pct = payload[keys.fetch(:percent)].to_f
return if pct >= opts.fetch(:threshold)
build_row(fname, pct, payload, opts, keys)
end
|
#run(args, stdout:, stderr:) ⇒ Object
23
24
25
26
27
28
29
30
31
32
33
|
# File 'lib/simplecov/cli/uncovered.rb', line 23
def run(args, stdout:, stderr:, **)
opts = parse(args)
issue = Annotations.issue(opts)
return error(stderr, issue) if issue
keys = CoverageFile::CRITERIA[opts.fetch(:criterion)]
return unknown_criterion(opts.fetch(:criterion), stderr) unless keys
opts[:missing] = true if opts.fetch(:annotate)
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
|
#validate_top(value) ⇒ Object
A negative count would raise from Array#first, so it is reported as the
parse error it is. --top 0 is allowed and shows nothing. OptionParser
prepends the offending option's name, so the raise carries only the reason.
73
74
75
76
77
|
# File 'lib/simplecov/cli/uncovered.rb', line 73
def validate_top(value)
raise OptionParser::InvalidArgument, "must not be negative" if value.negative?
value
end
|