single_cov 1.11.0 → 2.1.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/version.rb +1 -1
- data/lib/single_cov.rb +56 -51
- metadata +89 -9
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 03abb741a629409eca737e84185cbd61c34a24a65fdb5b4c381d295f00690eed
|
|
4
|
+
data.tar.gz: fee46d0a03e4812f372c375745ff9a02229292bc1c153e028ee7dc46691edfb0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 52da7209346a1ec927241e0db7390d664ef155a6146642e0895964cbcaa7c6e704ee6dc027591032fcb4727546543de60aa68ddd57f9b7e5f8879b9c98169a73
|
|
7
|
+
data.tar.gz: 3f0ae6f966cb07c608efd71cc8b87787c7506363c8bf2e43c4e334cf88b51122f56d2ad56864afc302b7158339eb4c5f3d8935f8a924c3132e43ab216604f700
|
data/lib/single_cov/version.rb
CHANGED
data/lib/single_cov.rb
CHANGED
|
@@ -4,6 +4,7 @@ module SingleCov
|
|
|
4
4
|
MAX_OUTPUT = Integer(ENV["SINGLE_COV_MAX_OUTPUT"] || "40")
|
|
5
5
|
RAILS_APP_FOLDERS = ["models", "serializers", "helpers", "controllers", "mailers", "views", "jobs", "channels"]
|
|
6
6
|
UNCOVERED_COMMENT_MARKER = /#.*uncovered/
|
|
7
|
+
NOCOV_MARKER = /^\s*#\s*:nocov:/ # see https://github.com/simplecov-ruby/simplecov/blob/00376ea2f29ce7a7355b7c2d7d094b666b57cb9b/lib/simplecov/lines_classifier.rb#L16
|
|
7
8
|
PREFIXES_TO_IGNORE = [] # things to not prefix with lib/ etc
|
|
8
9
|
|
|
9
10
|
class << self
|
|
@@ -32,7 +33,7 @@ module SingleCov
|
|
|
32
33
|
|
|
33
34
|
def all_covered?(result)
|
|
34
35
|
errors = COVERAGES.flat_map do |file, expected_uncovered|
|
|
35
|
-
next no_coverage_error(file) unless coverage = result["#{root}/#{file}"]
|
|
36
|
+
next no_coverage_error(file) unless (coverage = result["#{root}/#{file}"])
|
|
36
37
|
|
|
37
38
|
uncovered = uncovered(coverage)
|
|
38
39
|
next if uncovered.size == expected_uncovered
|
|
@@ -40,8 +41,10 @@ module SingleCov
|
|
|
40
41
|
# ignore lines that are marked as uncovered via comments
|
|
41
42
|
# TODO: warn when using uncovered but the section is indeed covered
|
|
42
43
|
content = File.readlines("#{root}/#{file}")
|
|
44
|
+
nocov_lines_nums = nocov_line_numbers(content)
|
|
43
45
|
uncovered.reject! do |line_start, _, _, _, _|
|
|
44
|
-
content[line_start - 1].match?(UNCOVERED_COMMENT_MARKER)
|
|
46
|
+
content[line_start - 1].match?(UNCOVERED_COMMENT_MARKER) ||
|
|
47
|
+
nocov_lines_nums.include?(line_start)
|
|
45
48
|
end
|
|
46
49
|
next if uncovered.size == expected_uncovered
|
|
47
50
|
|
|
@@ -119,8 +122,7 @@ module SingleCov
|
|
|
119
122
|
|
|
120
123
|
case framework
|
|
121
124
|
when :minitest
|
|
122
|
-
|
|
123
|
-
return if minitest_running_subset_of_tests?
|
|
125
|
+
return if minitest_running_subset_of_tests?(ARGV)
|
|
124
126
|
when :rspec
|
|
125
127
|
return if rspec_running_subset_of_tests?
|
|
126
128
|
else
|
|
@@ -129,15 +131,35 @@ module SingleCov
|
|
|
129
131
|
|
|
130
132
|
start_coverage_recording
|
|
131
133
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
134
|
+
# minitest overrides at_exit, so we need to get into it to execute after it finishes
|
|
135
|
+
# so when using the `minitest` executable or loading minitest before SingleCov the first branch is used
|
|
136
|
+
if defined?(Minitest)
|
|
137
|
+
(class << Minitest; self; end).prepend(Module.new do
|
|
138
|
+
def run(args = [])
|
|
139
|
+
original_args = args.dup # minitest modified them
|
|
140
|
+
result = super
|
|
141
|
+
if result && !SingleCov.send(:minitest_running_subset_of_tests?, original_args)
|
|
142
|
+
return SingleCov.report_at_exit
|
|
143
|
+
end
|
|
144
|
+
result
|
|
145
|
+
end
|
|
146
|
+
end)
|
|
147
|
+
else
|
|
148
|
+
override_at_exit do |status, _exception|
|
|
149
|
+
if main_process? && status == 0 && !report_at_exit
|
|
150
|
+
exit 1
|
|
151
|
+
end
|
|
137
152
|
end
|
|
138
153
|
end
|
|
139
154
|
end
|
|
140
155
|
|
|
156
|
+
def report_at_exit
|
|
157
|
+
return unless enabled?
|
|
158
|
+
results = coverage_results
|
|
159
|
+
generate_report results
|
|
160
|
+
SingleCov.all_covered?(results)
|
|
161
|
+
end
|
|
162
|
+
|
|
141
163
|
# use this in forks when using rspec to silence duplicated output
|
|
142
164
|
def disable
|
|
143
165
|
@disabled = true
|
|
@@ -159,7 +181,7 @@ module SingleCov
|
|
|
159
181
|
end
|
|
160
182
|
|
|
161
183
|
def enabled?
|
|
162
|
-
|
|
184
|
+
!defined?(@disabled) || !@disabled
|
|
163
185
|
end
|
|
164
186
|
|
|
165
187
|
# assuming that the main process will load all the files, we store it's pid
|
|
@@ -168,7 +190,7 @@ module SingleCov
|
|
|
168
190
|
end
|
|
169
191
|
|
|
170
192
|
def main_process?
|
|
171
|
-
|
|
193
|
+
!defined?(@main_process_pid) || @main_process_pid == Process.pid
|
|
172
194
|
end
|
|
173
195
|
|
|
174
196
|
# {[branch_id] => {[branch_part] => coverage}} --> uncovered location
|
|
@@ -196,6 +218,19 @@ module SingleCov
|
|
|
196
218
|
Dir["#{root}/#{pattern}"].map! { |f| f.sub("#{root}/", '') }
|
|
197
219
|
end
|
|
198
220
|
|
|
221
|
+
# @returns [Integer] 1-based line numbers that are inside :nocov: blocks
|
|
222
|
+
def nocov_line_numbers(content)
|
|
223
|
+
inside = false
|
|
224
|
+
content.each_with_index.filter_map do |line, index|
|
|
225
|
+
if line.match?(NOCOV_MARKER)
|
|
226
|
+
inside = !inside # toggle
|
|
227
|
+
nil # line itself cannot be uncovered since it is only a comment
|
|
228
|
+
elsif inside
|
|
229
|
+
index + 1
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
|
|
199
234
|
def indexes(list, find)
|
|
200
235
|
list.each_with_index.filter_map { |v, i| i if v == find }
|
|
201
236
|
end
|
|
@@ -230,56 +265,26 @@ module SingleCov
|
|
|
230
265
|
COVERAGES.size == 1
|
|
231
266
|
end
|
|
232
267
|
|
|
233
|
-
# we cannot insert our hooks when minitest is already running
|
|
234
|
-
def minitest_should_not_be_running!
|
|
235
|
-
return unless defined?(Minitest)
|
|
236
|
-
return unless Minitest.class_variable_defined?(:@@installed_at_exit)
|
|
237
|
-
return unless Minitest.class_variable_get(:@@installed_at_exit)
|
|
238
|
-
|
|
239
|
-
# untested
|
|
240
|
-
# https://github.com/rails/rails/pull/26515 rails loads autorun before test
|
|
241
|
-
# but it works out for some reason
|
|
242
|
-
return if Minitest.extensions.include?('rails')
|
|
243
|
-
|
|
244
|
-
# untested
|
|
245
|
-
# forking test runner does some hacky acrobatics to fake minitest status
|
|
246
|
-
# and the resets it ... works out ok in the end ...
|
|
247
|
-
return if faked_by_forking_test_runner?
|
|
248
|
-
|
|
249
|
-
# ... but only if it's used with `--merge-coverage` otherwise the coverage reporting is useless
|
|
250
|
-
if $0.end_with?("/forking-test-runner")
|
|
251
|
-
raise "forking-test-runner only work with single_cov when using --merge-coverage"
|
|
252
|
-
end
|
|
253
|
-
|
|
254
|
-
raise "Load minitest after setting up SingleCov"
|
|
255
|
-
end
|
|
256
|
-
|
|
257
|
-
# ForkingTestRunner fakes an initialized minitest to avoid multiple hooks being installed
|
|
258
|
-
# so hooks still get added in order https://github.com/grosser/forking_test_runner/pull/4
|
|
259
|
-
def faked_by_forking_test_runner?
|
|
260
|
-
defined?(Coverage) && Coverage.respond_to?(:capture_coverage!)
|
|
261
|
-
end
|
|
262
|
-
|
|
263
268
|
# do not record or verify when only running selected tests since it would be missing data
|
|
264
|
-
def minitest_running_subset_of_tests?
|
|
269
|
+
def minitest_running_subset_of_tests?(argv)
|
|
265
270
|
# via direct option (ruby test.rb -n /foo/)
|
|
266
|
-
|
|
271
|
+
# or `minitest foo.rb:123` which is translated to -n
|
|
272
|
+
argv.map { |a| a.split('=', 2).first }.intersect?(['-n', '--name', '-l', '--line']) ||
|
|
267
273
|
|
|
268
|
-
# via testrbl
|
|
269
|
-
(
|
|
274
|
+
# via testrbl, mtest, or rails with direct line number (mtest test.rb:123)
|
|
275
|
+
(argv.first =~ /:\d+\Z/) ||
|
|
270
276
|
|
|
271
277
|
# via rails test which preloads mintest, removes ARGV and fills options
|
|
272
278
|
(
|
|
273
|
-
defined?(Minitest) &&
|
|
274
279
|
defined?(Minitest.reporter) &&
|
|
275
280
|
Minitest.reporter &&
|
|
276
281
|
(reporter = Minitest.reporter.reporters.first) &&
|
|
277
|
-
reporter.options[:filter]
|
|
282
|
+
(reporter.options[:filter] || reporter.options[:include]) # MT 5 vs MT 6
|
|
278
283
|
)
|
|
279
284
|
end
|
|
280
285
|
|
|
281
286
|
def rspec_running_subset_of_tests?
|
|
282
|
-
(
|
|
287
|
+
ARGV.intersect?(['-t', '--tag', '-e', '--example']) || ARGV.any? { |a| a =~ /:\d+$|\[[\d:]+\]$/ }
|
|
283
288
|
end
|
|
284
289
|
|
|
285
290
|
# code stolen from SimpleCov
|
|
@@ -400,7 +405,7 @@ module SingleCov
|
|
|
400
405
|
end
|
|
401
406
|
|
|
402
407
|
# remove test extension
|
|
403
|
-
if !file_part.sub!(/_(?:test|spec)\.rb\b.*/, '.rb') && !file_part.sub!(
|
|
408
|
+
if !file_part.sub!(/_(?:test|spec)\.rb\b.*/, '.rb') && !file_part.sub!('/test_', "/")
|
|
404
409
|
raise "Unable to remove test extension from #{file} ... /test_, _test.rb and _spec.rb are supported"
|
|
405
410
|
end
|
|
406
411
|
end
|
|
@@ -418,14 +423,14 @@ module SingleCov
|
|
|
418
423
|
end
|
|
419
424
|
|
|
420
425
|
def generate_report(results)
|
|
421
|
-
return unless report = coverage_report
|
|
426
|
+
return unless (report = coverage_report)
|
|
422
427
|
|
|
423
428
|
# not a hard dependency for the whole library
|
|
424
429
|
require "json"
|
|
425
430
|
require "fileutils"
|
|
426
431
|
|
|
427
432
|
used = COVERAGES.map { |f, _| "#{root}/#{f}" }
|
|
428
|
-
covered = results.
|
|
433
|
+
covered = results.slice(*used)
|
|
429
434
|
|
|
430
435
|
if coverage_report_lines
|
|
431
436
|
covered = covered.transform_values { |v| v.is_a?(Hash) ? v.fetch(:lines) : v }
|
metadata
CHANGED
|
@@ -1,16 +1,98 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: single_cov
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 2.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Michael Grosser
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
12
|
-
dependencies:
|
|
13
|
-
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: bump
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '0'
|
|
19
|
+
type: :development
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '0'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: minitest
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '0'
|
|
33
|
+
type: :development
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '0'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: rake
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - ">="
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '0'
|
|
47
|
+
type: :development
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - ">="
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '0'
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: rspec
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - ">="
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '0'
|
|
61
|
+
type: :development
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - ">="
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '0'
|
|
68
|
+
- !ruby/object:Gem::Dependency
|
|
69
|
+
name: rubocop
|
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - ">="
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '0'
|
|
75
|
+
type: :development
|
|
76
|
+
prerelease: false
|
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - ">="
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '0'
|
|
82
|
+
- !ruby/object:Gem::Dependency
|
|
83
|
+
name: simplecov
|
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
|
85
|
+
requirements:
|
|
86
|
+
- - ">="
|
|
87
|
+
- !ruby/object:Gem::Version
|
|
88
|
+
version: '0'
|
|
89
|
+
type: :development
|
|
90
|
+
prerelease: false
|
|
91
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
92
|
+
requirements:
|
|
93
|
+
- - ">="
|
|
94
|
+
- !ruby/object:Gem::Version
|
|
95
|
+
version: '0'
|
|
14
96
|
email: michael@grosser.it
|
|
15
97
|
executables: []
|
|
16
98
|
extensions: []
|
|
@@ -23,7 +105,6 @@ homepage: https://github.com/grosser/single_cov
|
|
|
23
105
|
licenses:
|
|
24
106
|
- MIT
|
|
25
107
|
metadata: {}
|
|
26
|
-
post_install_message:
|
|
27
108
|
rdoc_options: []
|
|
28
109
|
require_paths:
|
|
29
110
|
- lib
|
|
@@ -31,15 +112,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
31
112
|
requirements:
|
|
32
113
|
- - ">="
|
|
33
114
|
- !ruby/object:Gem::Version
|
|
34
|
-
version: 2.
|
|
115
|
+
version: 3.2.0
|
|
35
116
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
36
117
|
requirements:
|
|
37
118
|
- - ">="
|
|
38
119
|
- !ruby/object:Gem::Version
|
|
39
120
|
version: '0'
|
|
40
121
|
requirements: []
|
|
41
|
-
rubygems_version: 3.
|
|
42
|
-
signing_key:
|
|
122
|
+
rubygems_version: 3.6.9
|
|
43
123
|
specification_version: 4
|
|
44
124
|
summary: Actionable code coverage.
|
|
45
125
|
test_files: []
|