Module: SimpleCov::CLI::Coverage

Defined in:
lib/simplecov/cli/coverage.rb

Overview

‘simplecov coverage <path>` — print per-criterion stats for one file from a JSONFormatter coverage.json.

Constant Summary collapse

CRITERIA =
[
  {label: "Line",   pct: "lines_covered_percent",    cov: "covered_lines",    tot: "total_lines"},
  {label: "Branch", pct: "branches_covered_percent", cov: "covered_branches", tot: "total_branches"},
  {label: "Method", pct: "methods_covered_percent",  cov: "covered_methods",  tot: "total_methods"}
].freeze

Class Method Summary collapse

Class Method Details

.emit(match, opts, stdout) ⇒ Object



65
66
67
68
69
70
71
72
# File 'lib/simplecov/cli/coverage.rb', line 65

def emit(match, opts, stdout)
  filename, payload = match
  if opts[:json]
    stdout.puts(JSON.pretty_generate(filename => payload))
  else
    print_human(filename, payload, stdout, SimpleCov::CLI.color_enabled?(opts, stdout))
  end
end

.emit_criterion(stdout, payload, criterion, color) ⇒ Object



79
80
81
82
83
84
85
86
87
88
# File 'lib/simplecov/cli/coverage.rb', line 79

def emit_criterion(stdout, payload, criterion, color)
  return unless payload.key?(criterion[:pct])

  pct = payload[criterion[:pct]].to_f
  stdout.puts(format("  %<label>-7s %<pct>s (%<covered>d / %<total>d)",
                     label: "#{criterion[:label]}:",
                     pct: SimpleCov::Color.colorize_percent(pct, enabled: color),
                     covered: payload[criterion[:cov]] || 0,
                     total: payload[criterion[:tot]] || 0))
end

.locate_match(opts, stderr) ⇒ Object



44
45
46
47
48
49
50
51
52
53
# File 'lib/simplecov/cli/coverage.rb', line 44

def locate_match(opts, stderr)
  return stderr.puts("simplecov coverage: #{opts[:input]} not found") && nil unless File.exist?(opts[:input])

  data = JSON.parse(File.read(opts[:input]))
  match = lookup(data.fetch("coverage", {}), opts[:path])
  return match if match

  stderr.puts("simplecov coverage: no entry for #{opts[:path]} in #{opts[:input]}")
  nil
end

.lookup(coverage_hash, path) ⇒ Object

Match either the absolute path, the literal string passed, or any coverage entry whose absolute filename ends with “/<path>”. That covers the three natural ways a user types a path: relative to project root (“app/foo.rb”), absolute, or basename-only.



59
60
61
62
63
# File 'lib/simplecov/cli/coverage.rb', line 59

def lookup(coverage_hash, path)
  absolute = File.expand_path(path)
  suffix   = "/#{path}"
  coverage_hash.find { |fname, _| fname == absolute || fname == path || fname.end_with?(suffix) }
end

.parse(args, stderr:) ⇒ Object



30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/simplecov/cli/coverage.rb', line 30

def parse(args, stderr:)
  opts = {input: SimpleCov::CLI.default_input, json: false, no_color: false}
  rest =
    OptionParser.new do |o|
      o.on("--input PATH") { |v| opts[:input] = v }
      o.on("--json") { opts[:json] = true }
      o.on("--no-color") { opts[:no_color] = true }
    end.parse(args)
  return stderr.puts("simplecov coverage: missing file argument") && nil if rest.empty?

  opts[:path] = rest.first
  opts
end


74
75
76
77
# File 'lib/simplecov/cli/coverage.rb', line 74

def print_human(filename, payload, stdout, color)
  stdout.puts(filename)
  CRITERIA.each { |c| emit_criterion(stdout, payload, c, color) }
end

.run(args, stdout:, stderr:) ⇒ Object



19
20
21
22
23
24
25
26
27
28
# File 'lib/simplecov/cli/coverage.rb', line 19

def run(args, stdout:, stderr:)
  opts = parse(args, stderr: stderr)
  return 1 unless opts

  match = locate_match(opts, stderr)
  return 1 unless match

  emit(match, opts, stdout)
  0
end