Module: SingleCov

Defined in:
lib/single_cov.rb,
lib/single_cov/version.rb

Constant Summary collapse

COVERAGES =
[]
MAX_OUTPUT =
40
APP_FOLDERS =
["models", "serializers", "helpers", "controllers", "mailers", "views", "jobs"]
VERSION =
"0.3.1"

Class Method Summary collapse

Class Method Details

.all_covered?(result) ⇒ Boolean

Returns:

  • (Boolean)

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/single_cov.rb', line 20

def all_covered?(result)
  errors = COVERAGES.map do |file, expected_uncovered|
    if coverage = result["#{root}/#{file}"]
      uncovered_lines = coverage.each_with_index.map { |c, i| "#{file}:#{i+1}" if c == 0 }.compact
      next if uncovered_lines.size == expected_uncovered
      warn_about_bad_coverage(file, expected_uncovered, uncovered_lines)
    else
      warn_about_no_coverage(file)
    end
  end.compact

  return true if errors.empty?

  errors = errors.join("\n").split("\n") # unify arrays with multiline strings
  errors[MAX_OUTPUT..-1] = "... coverage output truncated" if errors.size >= MAX_OUTPUT
  warn errors

  errors.all? { |l| l.end_with?('?') } # ok if we just have warnings
end

.assert_tested(files: glob('{app,lib}/**/*.rb'), tests: default_tests, untested: []) ⇒ Object


49
50
51
52
53
54
55
56
57
58
59
# File 'lib/single_cov.rb', line 49

def assert_tested(files: glob('{app,lib}/**/*.rb'), tests: default_tests, untested: [])
  missing = files - tests.map { |t| file_under_test(t) }
  fixed = untested - missing
  missing -= untested

  if fixed.any?
    raise "Remove #{fixed.inspect} from untested!"
  elsif missing.any?
    raise missing.map { |f| "missing test for #{f}" }.join("\n")
  end
end

.assert_used(tests: default_tests) ⇒ Object


40
41
42
43
44
45
46
47
# File 'lib/single_cov.rb', line 40

def assert_used(tests: default_tests)
  bad = tests.select do |file|
    File.read(file) !~ /SingleCov.(not_)?covered\!/
  end
  unless bad.empty?
    raise bad.map { |f| "#{f}: needs to use SingleCov.covered!" }.join("\n")
  end
end

.covered!(file: nil, uncovered: 0) ⇒ Object


15
16
17
18
# File 'lib/single_cov.rb', line 15

def covered!(file: nil, uncovered: 0)
  file = guess_and_check_covered_file(file)
  COVERAGES << [file, uncovered]
end

.not_covered!Object


12
13
# File 'lib/single_cov.rb', line 12

def not_covered!
end

.rewrite(&block) ⇒ Object

optionally rewrite the file we guessed with a lambda


8
9
10
# File 'lib/single_cov.rb', line 8

def rewrite(&block)
  @rewrite = block
end

.setup(framework, root: nil) ⇒ Object


61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/single_cov.rb', line 61

def setup(framework, root: nil)
  if defined?(SimpleCov)
    raise "Load SimpleCov after SingleCov"
  end

  @root = root if root

  case framework
  when :minitest
    minitest_should_not_be_running!
    return if minitest_running_subset_of_tests?
  when :rspec
    return if rspec_running_subset_of_tests?
  else
    raise "Unsupported framework #{framework.inspect}"
  end

  start_coverage_recording

  override_at_exit do |status, _exception|
    exit 1 if status == 0 && !SingleCov.all_covered?(coverage_results)
  end
end