single_cov 1.1.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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.
|