single_cov 1.1.0 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/single_cov.rb +66 -13
- data/lib/single_cov/version.rb +1 -1
- metadata +3 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6cd1fb991b879dcaf753d2aa30c4f94ac3f97659cf602df4f9adab874046c16f
|
4
|
+
data.tar.gz: c2351364b4482ceff98314b881fd5b774e9040c117479674b8fb41c0b550dac4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 813924bc4aaad528db8afe9640178f3cfad2c11ffa4042573e4810a83cf941014e3d77352436b1c999330c70c066619054b88a3117e5d87885f95ce619dfaf2d
|
7
|
+
data.tar.gz: 31915f85ff52971fb4691f1fe52680c026b8f8e70c6b390b0c538e84ced5e59b035803130f09d5df03f4eba7731608c46f02ba28df366506322559495baf588d
|
data/lib/single_cov.rb
CHANGED
@@ -3,41 +3,62 @@ module SingleCov
|
|
3
3
|
MAX_OUTPUT = 40
|
4
4
|
APP_FOLDERS = ["models", "serializers", "helpers", "controllers", "mailers", "views", "jobs", "channels"]
|
5
5
|
BRANCH_COVERAGE_SUPPORTED = (RUBY_VERSION >= "2.5.0")
|
6
|
+
UNCOVERED_COMMENT_MARKER = "uncovered"
|
6
7
|
|
7
8
|
class << self
|
9
|
+
# enable coverage reporting, changed by forking-test-runner to combine multiple reports
|
10
|
+
attr_accessor :coverage_report
|
11
|
+
|
8
12
|
# optionally rewrite the file we guessed with a lambda
|
9
13
|
def rewrite(&block)
|
10
14
|
@rewrite = block
|
11
15
|
end
|
12
16
|
|
13
17
|
def not_covered!
|
18
|
+
store_pid
|
14
19
|
end
|
15
20
|
|
16
21
|
def covered!(file: nil, uncovered: 0)
|
17
22
|
file = guess_and_check_covered_file(file)
|
18
23
|
COVERAGES << [file, uncovered]
|
24
|
+
store_pid
|
19
25
|
end
|
20
26
|
|
21
27
|
def all_covered?(result)
|
22
28
|
errors = COVERAGES.map do |file, expected_uncovered|
|
23
29
|
if coverage = result["#{root}/#{file}"]
|
24
30
|
line_coverage = (coverage.is_a?(Hash) ? coverage.fetch(:lines) : coverage)
|
25
|
-
|
31
|
+
uncovered_lines = line_coverage.each_with_index.map { |c, i| i + 1 if c == 0 }.compact
|
32
|
+
|
26
33
|
branch_coverage = (coverage.is_a?(Hash) && coverage[:branches])
|
34
|
+
uncovered_branches = (branch_coverage ? uncovered_branches(branch_coverage, uncovered_lines) : [])
|
27
35
|
|
28
|
-
|
29
|
-
|
30
|
-
end
|
36
|
+
uncovered = uncovered_lines.concat uncovered_branches
|
37
|
+
next if uncovered.size == expected_uncovered
|
31
38
|
|
39
|
+
# ignore lines that are marked as uncovered via comments
|
40
|
+
# NOTE: ideally we should also warn when using uncovered but the section is indeed covered
|
41
|
+
content = File.readlines(file)
|
42
|
+
uncovered.reject! do |line_start, _, _, _|
|
43
|
+
content[line_start - 1].include?(UNCOVERED_COMMENT_MARKER)
|
44
|
+
end
|
32
45
|
next if uncovered.size == expected_uncovered
|
33
46
|
|
34
|
-
# branches are unsorted and added to the end, only sort when
|
47
|
+
# branches are unsorted and added to the end, only sort when displayed
|
35
48
|
if branch_coverage
|
36
|
-
uncovered.sort_by! { |line_start, char_start,
|
49
|
+
uncovered.sort_by! { |line_start, char_start, _, _| [line_start, char_start || 0] }
|
37
50
|
end
|
38
51
|
|
39
52
|
uncovered.map! do |line_start, char_start, line_end, char_end|
|
40
|
-
char_start
|
53
|
+
if char_start # branch coverage
|
54
|
+
if line_start == line_end
|
55
|
+
"#{file}:#{line_start}:#{char_start}-#{char_end}"
|
56
|
+
else # possibly unreachable since branches always seem to be on the same line
|
57
|
+
"#{file}:#{line_start}:#{char_start}-#{line_end}:#{char_end}"
|
58
|
+
end
|
59
|
+
else
|
60
|
+
"#{file}:#{line_start}"
|
61
|
+
end
|
41
62
|
end
|
42
63
|
|
43
64
|
warn_about_bad_coverage(file, expected_uncovered, uncovered)
|
@@ -100,7 +121,11 @@ module SingleCov
|
|
100
121
|
start_coverage_recording
|
101
122
|
|
102
123
|
override_at_exit do |status, _exception|
|
103
|
-
|
124
|
+
if enabled? && main_process? && status == 0
|
125
|
+
results = coverage_results
|
126
|
+
generate_report results
|
127
|
+
exit 1 unless SingleCov.all_covered?(results)
|
128
|
+
end
|
104
129
|
end
|
105
130
|
end
|
106
131
|
|
@@ -111,7 +136,19 @@ module SingleCov
|
|
111
136
|
|
112
137
|
private
|
113
138
|
|
114
|
-
def
|
139
|
+
def enabled?
|
140
|
+
(!defined?(@disabled) || !@disabled)
|
141
|
+
end
|
142
|
+
|
143
|
+
def store_pid
|
144
|
+
@pid = Process.pid
|
145
|
+
end
|
146
|
+
|
147
|
+
def main_process?
|
148
|
+
(!defined?(@pid) || @pid == Process.pid)
|
149
|
+
end
|
150
|
+
|
151
|
+
def uncovered_branches(coverage, uncovered_lines)
|
115
152
|
# {[branch_id] => {[branch_part] => coverage}} --> {branch_part -> sum-of-coverage}
|
116
153
|
sum = Hash.new(0)
|
117
154
|
coverage.each_value do |branch|
|
@@ -121,8 +158,8 @@ module SingleCov
|
|
121
158
|
end
|
122
159
|
|
123
160
|
# show missing coverage
|
124
|
-
|
125
|
-
|
161
|
+
sum.select! { |k, v| v.zero? && !uncovered_lines.include?(k[0]) }
|
162
|
+
found = sum.map { |k, _| [k[0], k[1]+1, k[2], k[3]+1] }
|
126
163
|
found.uniq!
|
127
164
|
found
|
128
165
|
end
|
@@ -313,8 +350,8 @@ module SingleCov
|
|
313
350
|
end
|
314
351
|
|
315
352
|
# remove test extension
|
316
|
-
|
317
|
-
raise "Unable to remove test extension from #{file} ... _test.rb and _spec.rb are supported"
|
353
|
+
if !file_part.sub!(/_(?:test|spec)\.rb\b.*/, '.rb') && !file_part.sub!(/\/test_/, "/")
|
354
|
+
raise "Unable to remove test extension from #{file} ... /test_, _test.rb and _spec.rb are supported"
|
318
355
|
end
|
319
356
|
|
320
357
|
# put back the subfolder
|
@@ -328,5 +365,21 @@ module SingleCov
|
|
328
365
|
def root
|
329
366
|
@root ||= (defined?(Bundler) && Bundler.root.to_s.sub(/\/gemfiles$/, '')) || Dir.pwd
|
330
367
|
end
|
368
|
+
|
369
|
+
def generate_report(results)
|
370
|
+
return unless report = coverage_report
|
371
|
+
|
372
|
+
# not a hard dependency for the whole library
|
373
|
+
require "json"
|
374
|
+
require "fileutils"
|
375
|
+
|
376
|
+
used = COVERAGES.map { |f, _| "#{root}/#{f}" }
|
377
|
+
covered = results.select { |k, _| used.include?(k) }
|
378
|
+
data = JSON.pretty_generate(
|
379
|
+
"Unit Tests" => {"coverage" => covered, "timestamp" => Time.now.to_i }
|
380
|
+
)
|
381
|
+
FileUtils.mkdir_p(File.dirname(report))
|
382
|
+
File.write report, data
|
383
|
+
end
|
331
384
|
end
|
332
385
|
end
|
data/lib/single_cov/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: single_cov
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Grosser
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-10-24 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description:
|
14
14
|
email: michael@grosser.it
|
@@ -38,8 +38,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
38
38
|
- !ruby/object:Gem::Version
|
39
39
|
version: '0'
|
40
40
|
requirements: []
|
41
|
-
|
42
|
-
rubygems_version: 2.7.6
|
41
|
+
rubygems_version: 3.1.3
|
43
42
|
signing_key:
|
44
43
|
specification_version: 4
|
45
44
|
summary: Actionable code coverage.
|