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(opts, stdout) ⇒ Object
-
#empty_message(json) ⇒ Object
-
#format_row(fname, pct, covered, total, color) ⇒ Object
-
#own_options(parser, options) ⇒ Object
-
#parse(args) ⇒ Object
-
#precheck(opts) ⇒ 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
128
129
130
131
132
|
# File 'lib/simplecov/cli/uncovered.rb', line 128
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
64
65
66
67
68
|
# File 'lib/simplecov/cli/uncovered.rb', line 64
def emit(stdout, files, opts)
return Misses.annotate(stdout, files) if opts.fetch(:annotate)
opts.fetch(:json) ? emit_json(stdout, files) : emit_text(stdout, files, CLI.color_enabled?(opts, stdout))
end
|
#emit_json(stdout, files) ⇒ Object
101
102
103
104
105
106
107
108
|
# File 'lib/simplecov/cli/uncovered.rb', line 101
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
93
94
95
96
97
98
99
|
# File 'lib/simplecov/cli/uncovered.rb', line 93
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(opts, stdout) ⇒ Object
54
55
56
57
|
# File 'lib/simplecov/cli/uncovered.rb', line 54
def empty(opts, stdout)
stdout.puts(empty_message(opts.fetch(:json))) unless opts.fetch(:annotate)
0
end
|
#empty_message(json) ⇒ Object
110
111
112
|
# File 'lib/simplecov/cli/uncovered.rb', line 110
def empty_message(json)
json ? "[]" : "simplecov uncovered: nothing to report"
end
|
134
135
136
137
138
|
# File 'lib/simplecov/cli/uncovered.rb', line 134
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
76
77
78
79
80
81
82
|
# File 'lib/simplecov/cli/uncovered.rb', line 76
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
70
71
72
73
74
|
# File 'lib/simplecov/cli/uncovered.rb', line 70
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
|
#precheck(opts) ⇒ Object
34
35
36
37
38
39
40
41
|
# File 'lib/simplecov/cli/uncovered.rb', line 34
def precheck(opts)
return nil unless opts.fetch(:annotate)
unless opts.fetch(:annotate).eql?("github")
return "unknown --annotate #{opts.fetch(:annotate).inspect} (only github is supported)"
end
"cannot combine --annotate with --json" if opts.fetch(:json)
end
|
#rank(coverage_hash, opts, keys) ⇒ Object
114
115
116
117
|
# File 'lib/simplecov/cli/uncovered.rb', line 114
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
43
44
45
46
47
48
49
50
51
52
|
# File 'lib/simplecov/cli/uncovered.rb', line 43
def report(opts, keys, stdout, stderr)
coverage = CoverageFile.load_coverage(opts.fetch(:input), command: "uncovered", stderr: stderr)
return 1 unless coverage
files = rank(coverage, opts, keys).first(opts.fetch(:top))
return empty(opts, stdout) if files.empty?
emit(stdout, files, opts)
0
end
|
#row_for(fname, payload, opts, keys) ⇒ Object
119
120
121
122
123
124
125
126
|
# File 'lib/simplecov/cli/uncovered.rb', line 119
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
22
23
24
25
26
27
28
29
30
31
32
|
# File 'lib/simplecov/cli/uncovered.rb', line 22
def run(args, stdout:, stderr:, **)
opts = parse(args)
issue = precheck(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
59
60
61
62
|
# File 'lib/simplecov/cli/uncovered.rb', line 59
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.
87
88
89
90
91
|
# File 'lib/simplecov/cli/uncovered.rb', line 87
def validate_top(value)
raise OptionParser::InvalidArgument, "must not be negative" if value.negative?
value
end
|