simplecov 0.17.1 → 0.21.1
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/CHANGELOG.md +100 -434
- data/README.md +375 -93
- data/doc/alternate-formatters.md +16 -1
- data/doc/commercial-services.md +5 -0
- data/lib/minitest/simplecov_plugin.rb +15 -0
- data/lib/simplecov.rb +294 -128
- data/lib/simplecov/combine.rb +30 -0
- data/lib/simplecov/combine/branches_combiner.rb +32 -0
- data/lib/simplecov/combine/files_combiner.rb +24 -0
- data/lib/simplecov/combine/lines_combiner.rb +43 -0
- data/lib/simplecov/combine/results_combiner.rb +60 -0
- data/lib/simplecov/command_guesser.rb +6 -3
- data/lib/simplecov/configuration.rb +191 -15
- data/lib/simplecov/coverage_statistics.rb +56 -0
- data/lib/simplecov/default_formatter.rb +20 -0
- data/lib/simplecov/defaults.rb +14 -13
- data/lib/simplecov/exit_codes.rb +5 -0
- data/lib/simplecov/exit_codes/exit_code_handling.rb +29 -0
- data/lib/simplecov/exit_codes/maximum_coverage_drop_check.rb +73 -0
- data/lib/simplecov/exit_codes/minimum_coverage_by_file_check.rb +54 -0
- data/lib/simplecov/exit_codes/minimum_overall_coverage_check.rb +53 -0
- data/lib/simplecov/file_list.rb +72 -13
- data/lib/simplecov/filter.rb +9 -6
- data/lib/simplecov/formatter.rb +2 -2
- data/lib/simplecov/formatter/multi_formatter.rb +5 -7
- data/lib/simplecov/formatter/simple_formatter.rb +4 -4
- data/lib/simplecov/last_run.rb +3 -1
- data/lib/simplecov/lines_classifier.rb +5 -5
- data/lib/simplecov/no_defaults.rb +1 -1
- data/lib/simplecov/process.rb +19 -0
- data/lib/simplecov/profiles.rb +9 -7
- data/lib/simplecov/result.rb +18 -12
- data/lib/simplecov/result_adapter.rb +30 -0
- data/lib/simplecov/result_merger.rb +130 -59
- data/lib/simplecov/simulate_coverage.rb +29 -0
- data/lib/simplecov/source_file.rb +272 -126
- data/lib/simplecov/source_file/branch.rb +84 -0
- data/lib/simplecov/source_file/line.rb +72 -0
- data/lib/simplecov/useless_results_remover.rb +18 -0
- data/lib/simplecov/version.rb +1 -1
- metadata +44 -158
- data/CONTRIBUTING.md +0 -51
- data/ISSUE_TEMPLATE.md +0 -23
- data/lib/simplecov/jruby_fix.rb +0 -44
- data/lib/simplecov/railtie.rb +0 -9
- data/lib/simplecov/railties/tasks.rake +0 -13
- data/lib/simplecov/raw_coverage.rb +0 -41
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SimpleCov
|
4
|
+
# Functionally for combining coverage results
|
5
|
+
#
|
6
|
+
module Combine
|
7
|
+
module_function
|
8
|
+
|
9
|
+
#
|
10
|
+
# Combine two coverage based on the given combiner_module.
|
11
|
+
#
|
12
|
+
# Combiners should always be called through this interface,
|
13
|
+
# as it takes care of short-circuiting of one of the coverages is nil.
|
14
|
+
#
|
15
|
+
# @return [Hash]
|
16
|
+
def combine(combiner_module, coverage_a, coverage_b)
|
17
|
+
return existing_coverage(coverage_a, coverage_b) if empty_coverage?(coverage_a, coverage_b)
|
18
|
+
|
19
|
+
combiner_module.combine(coverage_a, coverage_b)
|
20
|
+
end
|
21
|
+
|
22
|
+
def empty_coverage?(coverage_a, coverage_b)
|
23
|
+
!(coverage_a && coverage_b)
|
24
|
+
end
|
25
|
+
|
26
|
+
def existing_coverage(coverage_a, coverage_b)
|
27
|
+
coverage_a || coverage_b
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SimpleCov
|
4
|
+
module Combine
|
5
|
+
#
|
6
|
+
# Combine different branch coverage results on single file.
|
7
|
+
#
|
8
|
+
# Should be called through `SimpleCov.combine`.
|
9
|
+
module BranchesCombiner
|
10
|
+
module_function
|
11
|
+
|
12
|
+
#
|
13
|
+
# Return merged branches or the existed brach if other is missing.
|
14
|
+
#
|
15
|
+
# Branches inside files are always same if they exist, the difference only in coverage count.
|
16
|
+
# Branch coverage report for any conditional case is built from hash, it's key is a condition and
|
17
|
+
# it's body is a hash << keys from condition and value is coverage rate >>.
|
18
|
+
# ex: branches =>{ [:if, 3, 8, 6, 8, 36] => {[:then, 4, 8, 6, 8, 12] => 1, [:else, 5, 8, 6, 8, 36]=>2}, other conditions...}
|
19
|
+
# We create copy of result and update it values depending on the combined branches coverage values.
|
20
|
+
#
|
21
|
+
# @return [Hash]
|
22
|
+
#
|
23
|
+
def combine(coverage_a, coverage_b)
|
24
|
+
coverage_a.merge(coverage_b) do |_condition, branches_inside_a, branches_inside_b|
|
25
|
+
branches_inside_a.merge(branches_inside_b) do |_branch, a_count, b_count|
|
26
|
+
a_count + b_count
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SimpleCov
|
4
|
+
module Combine
|
5
|
+
#
|
6
|
+
# Handle combining two coverage results for same file
|
7
|
+
#
|
8
|
+
# Should be called through `SimpleCov.combine`.
|
9
|
+
module FilesCombiner
|
10
|
+
module_function
|
11
|
+
|
12
|
+
#
|
13
|
+
# Combines the results for 2 coverages of a file.
|
14
|
+
#
|
15
|
+
# @return [Hash]
|
16
|
+
#
|
17
|
+
def combine(coverage_a, coverage_b)
|
18
|
+
combination = {"lines" => Combine.combine(LinesCombiner, coverage_a["lines"], coverage_b["lines"])}
|
19
|
+
combination["branches"] = Combine.combine(BranchesCombiner, coverage_a["branches"], coverage_b["branches"]) if SimpleCov.branch_coverage?
|
20
|
+
combination
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SimpleCov
|
4
|
+
module Combine
|
5
|
+
#
|
6
|
+
# Combine two different lines coverage results on same file
|
7
|
+
#
|
8
|
+
# Should be called through `SimpleCov.combine`.
|
9
|
+
module LinesCombiner
|
10
|
+
module_function
|
11
|
+
|
12
|
+
def combine(coverage_a, coverage_b)
|
13
|
+
coverage_a
|
14
|
+
.zip(coverage_b)
|
15
|
+
.map do |coverage_a_val, coverage_b_val|
|
16
|
+
merge_line_coverage(coverage_a_val, coverage_b_val)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Return depends on coverage in a specific line
|
21
|
+
#
|
22
|
+
# @param [Integer || nil] first_val
|
23
|
+
# @param [Integer || nil] second_val
|
24
|
+
#
|
25
|
+
# Logic:
|
26
|
+
#
|
27
|
+
# => nil + 0 = nil
|
28
|
+
# => nil + nil = nil
|
29
|
+
# => int + int = int
|
30
|
+
#
|
31
|
+
# @return [Integer || nil]
|
32
|
+
def merge_line_coverage(first_val, second_val)
|
33
|
+
sum = first_val.to_i + second_val.to_i
|
34
|
+
|
35
|
+
if sum.zero? && (first_val.nil? || second_val.nil?)
|
36
|
+
nil
|
37
|
+
else
|
38
|
+
sum
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SimpleCov
|
4
|
+
module Combine
|
5
|
+
# There might be reports from different kinds of tests,
|
6
|
+
# e.g. RSpec and Cucumber. We need to combine their results
|
7
|
+
# into unified one. This class does that.
|
8
|
+
# To unite the results on file basis, it leverages
|
9
|
+
# the combine of lines and branches inside each file within given results.
|
10
|
+
module ResultsCombiner
|
11
|
+
module_function
|
12
|
+
|
13
|
+
#
|
14
|
+
# Combine process explanation
|
15
|
+
# => ResultCombiner: define all present files between results and start combine on file level.
|
16
|
+
# ==> FileCombiner: collect result of next combine levels lines and branches.
|
17
|
+
# ===> LinesCombiner: combine lines results.
|
18
|
+
# ===> BranchesCombiner: combine branches results.
|
19
|
+
#
|
20
|
+
# @return [Hash]
|
21
|
+
#
|
22
|
+
def combine(*results)
|
23
|
+
results.reduce({}) do |combined_results, next_result|
|
24
|
+
combine_result_sets(combined_results, next_result)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
#
|
29
|
+
# Manage combining results on files level
|
30
|
+
#
|
31
|
+
# @param [Hash] combined_results
|
32
|
+
# @param [Hash] result
|
33
|
+
#
|
34
|
+
# @return [Hash]
|
35
|
+
#
|
36
|
+
def combine_result_sets(combined_results, result)
|
37
|
+
results_files = combined_results.keys | result.keys
|
38
|
+
|
39
|
+
results_files.each_with_object({}) do |file_name, file_combination|
|
40
|
+
file_combination[file_name] = combine_file_coverage(
|
41
|
+
combined_results[file_name],
|
42
|
+
result[file_name]
|
43
|
+
)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
#
|
48
|
+
# Combine two files coverage results
|
49
|
+
#
|
50
|
+
# @param [Hash] coverage_a
|
51
|
+
# @param [Hash] coverage_b
|
52
|
+
#
|
53
|
+
# @return [Hash]
|
54
|
+
#
|
55
|
+
def combine_file_coverage(coverage_a, coverage_b)
|
56
|
+
Combine.combine(Combine::FilesCombiner, coverage_a, coverage_b)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
#
|
4
|
-
# Helper that tries to find out what test suite is running (for SimpleCov.command_name)
|
5
|
-
#
|
6
3
|
module SimpleCov
|
4
|
+
#
|
5
|
+
# Helper that tries to find out what test suite is running (for SimpleCov.command_name)
|
6
|
+
#
|
7
7
|
module CommandGuesser
|
8
8
|
class << self
|
9
9
|
# Storage for the original command line call that invoked the test suite.
|
@@ -22,6 +22,7 @@ module SimpleCov
|
|
22
22
|
def from_env
|
23
23
|
# If being run from inside parallel_tests set the command name according to the process number
|
24
24
|
return unless ENV["PARALLEL_TEST_GROUPS"] && ENV["TEST_ENV_NUMBER"]
|
25
|
+
|
25
26
|
number = ENV["TEST_ENV_NUMBER"]
|
26
27
|
number = "1" if number.empty?
|
27
28
|
"(#{number}/#{ENV['PARALLEL_TEST_GROUPS']})"
|
@@ -48,6 +49,8 @@ module SimpleCov
|
|
48
49
|
"RSpec"
|
49
50
|
elsif defined?(Test::Unit)
|
50
51
|
"Unit Tests"
|
52
|
+
elsif defined?(Minitest)
|
53
|
+
"Minitest"
|
51
54
|
elsif defined?(MiniTest)
|
52
55
|
"MiniTest"
|
53
56
|
else
|
@@ -2,15 +2,16 @@
|
|
2
2
|
|
3
3
|
require "fileutils"
|
4
4
|
require "docile"
|
5
|
-
|
6
|
-
|
7
|
-
# Bundles the configuration options used for SimpleCov. All methods
|
8
|
-
# defined here are usable from SimpleCov directly. Please check out
|
9
|
-
# SimpleCov documentation for further info.
|
10
|
-
#
|
5
|
+
require_relative "formatter/multi_formatter"
|
6
|
+
|
11
7
|
module SimpleCov
|
12
|
-
|
13
|
-
|
8
|
+
#
|
9
|
+
# Bundles the configuration options used for SimpleCov. All methods
|
10
|
+
# defined here are usable from SimpleCov directly. Please check out
|
11
|
+
# SimpleCov documentation for further info.
|
12
|
+
#
|
13
|
+
module Configuration
|
14
|
+
attr_writer :filters, :groups, :formatter, :print_error_status
|
14
15
|
|
15
16
|
#
|
16
17
|
# The root for the project. This defaults to the
|
@@ -20,6 +21,8 @@ module SimpleCov
|
|
20
21
|
#
|
21
22
|
def root(root = nil)
|
22
23
|
return @root if defined?(@root) && root.nil?
|
24
|
+
|
25
|
+
@coverage_path = nil # invalidate cache
|
23
26
|
@root = File.expand_path(root || Dir.getwd)
|
24
27
|
end
|
25
28
|
|
@@ -30,6 +33,7 @@ module SimpleCov
|
|
30
33
|
#
|
31
34
|
def coverage_dir(dir = nil)
|
32
35
|
return @coverage_dir if defined?(@coverage_dir) && dir.nil?
|
36
|
+
|
33
37
|
@coverage_path = nil # invalidate cache
|
34
38
|
@coverage_dir = (dir || "coverage")
|
35
39
|
end
|
@@ -93,8 +97,10 @@ module SimpleCov
|
|
93
97
|
#
|
94
98
|
def formatter(formatter = nil)
|
95
99
|
return @formatter if defined?(@formatter) && formatter.nil?
|
100
|
+
|
96
101
|
@formatter = formatter
|
97
102
|
raise "No formatter configured. Please specify a formatter using SimpleCov.formatter = SimpleCov::Formatter::SimpleFormatter" unless @formatter
|
103
|
+
|
98
104
|
@formatter
|
99
105
|
end
|
100
106
|
|
@@ -116,6 +122,14 @@ module SimpleCov
|
|
116
122
|
end
|
117
123
|
end
|
118
124
|
|
125
|
+
#
|
126
|
+
# Whether we should print non-success status codes. This can be
|
127
|
+
# configured with the #print_error_status= method.
|
128
|
+
#
|
129
|
+
def print_error_status
|
130
|
+
defined?(@print_error_status) ? @print_error_status : true
|
131
|
+
end
|
132
|
+
|
119
133
|
#
|
120
134
|
# Certain code blocks (i.e. Ruby-implementation specific code) can be excluded from
|
121
135
|
# the coverage metrics by wrapping it inside # :nocov: comment blocks. The nocov token
|
@@ -125,6 +139,7 @@ module SimpleCov
|
|
125
139
|
#
|
126
140
|
def nocov_token(nocov_token = nil)
|
127
141
|
return @nocov_token if defined?(@nocov_token) && nocov_token.nil?
|
142
|
+
|
128
143
|
@nocov_token = (nocov_token || "nocov")
|
129
144
|
end
|
130
145
|
alias skip_token nocov_token
|
@@ -160,7 +175,6 @@ module SimpleCov
|
|
160
175
|
# options at once.
|
161
176
|
#
|
162
177
|
def configure(&block)
|
163
|
-
return false unless SimpleCov.usable?
|
164
178
|
Docile.dsl_eval(self, &block)
|
165
179
|
end
|
166
180
|
|
@@ -177,17 +191,66 @@ module SimpleCov
|
|
177
191
|
# end
|
178
192
|
#
|
179
193
|
def at_exit(&block)
|
180
|
-
return
|
194
|
+
return Proc.new unless running || block_given?
|
195
|
+
|
181
196
|
@at_exit = block if block_given?
|
182
197
|
@at_exit ||= proc { SimpleCov.result.format! }
|
183
198
|
end
|
184
199
|
|
200
|
+
# gets or sets the enabled_for_subprocess configuration
|
201
|
+
# when true, this will inject SimpleCov code into Process.fork
|
202
|
+
def enable_for_subprocesses(value = nil)
|
203
|
+
return @enable_for_subprocesses if defined?(@enable_for_subprocesses) && value.nil?
|
204
|
+
|
205
|
+
@enable_for_subprocesses = value || false
|
206
|
+
end
|
207
|
+
|
208
|
+
# gets the enabled_for_subprocess configuration
|
209
|
+
def enabled_for_subprocesses?
|
210
|
+
enable_for_subprocesses
|
211
|
+
end
|
212
|
+
|
213
|
+
#
|
214
|
+
# Gets or sets the behavior to start a new forked Process.
|
215
|
+
#
|
216
|
+
# By default, it will add " (Process #{pid})" to the command_name, and start SimpleCov in quiet mode
|
217
|
+
#
|
218
|
+
# Configure with:
|
219
|
+
#
|
220
|
+
# SimpleCov.at_fork do |pid|
|
221
|
+
# SimpleCov.start do
|
222
|
+
# # This needs a unique name so it won't be ovewritten
|
223
|
+
# SimpleCov.command_name "#{SimpleCov.command_name} (subprocess: #{pid})"
|
224
|
+
# # be quiet, the parent process will be in charge of using the regular formatter and checking coverage totals
|
225
|
+
# SimpleCov.print_error_status = false
|
226
|
+
# SimpleCov.formatter SimpleCov::Formatter::SimpleFormatter
|
227
|
+
# SimpleCov.minimum_coverage 0
|
228
|
+
# # start
|
229
|
+
# SimpleCov.start
|
230
|
+
# end
|
231
|
+
# end
|
232
|
+
#
|
233
|
+
def at_fork(&block)
|
234
|
+
@at_fork = block if block_given?
|
235
|
+
@at_fork ||= lambda { |pid|
|
236
|
+
# This needs a unique name so it won't be ovewritten
|
237
|
+
SimpleCov.command_name "#{SimpleCov.command_name} (subprocess: #{pid})"
|
238
|
+
# be quiet, the parent process will be in charge of using the regular formatter and checking coverage totals
|
239
|
+
SimpleCov.print_error_status = false
|
240
|
+
SimpleCov.formatter SimpleCov::Formatter::SimpleFormatter
|
241
|
+
SimpleCov.minimum_coverage 0
|
242
|
+
# start
|
243
|
+
SimpleCov.start
|
244
|
+
}
|
245
|
+
end
|
246
|
+
|
185
247
|
#
|
186
248
|
# Returns the project name - currently assuming the last dirname in
|
187
249
|
# the SimpleCov.root is this.
|
188
250
|
#
|
189
251
|
def project_name(new_name = nil)
|
190
252
|
return @project_name if defined?(@project_name) && @project_name && new_name.nil?
|
253
|
+
|
191
254
|
@project_name = new_name if new_name.is_a?(String)
|
192
255
|
@project_name ||= File.basename(root.split("/").last).capitalize.tr("_", " ")
|
193
256
|
end
|
@@ -225,7 +288,20 @@ module SimpleCov
|
|
225
288
|
# Default is 0% (disabled)
|
226
289
|
#
|
227
290
|
def minimum_coverage(coverage = nil)
|
228
|
-
@minimum_coverage ||=
|
291
|
+
return @minimum_coverage ||= {} unless coverage
|
292
|
+
|
293
|
+
coverage = {primary_coverage => coverage} if coverage.is_a?(Numeric)
|
294
|
+
|
295
|
+
raise_on_invalid_coverage(coverage, "minimum_coverage")
|
296
|
+
|
297
|
+
@minimum_coverage = coverage
|
298
|
+
end
|
299
|
+
|
300
|
+
def raise_on_invalid_coverage(coverage, coverage_setting)
|
301
|
+
coverage.each_key { |criterion| raise_if_criterion_disabled(criterion) }
|
302
|
+
coverage.each_value do |percent|
|
303
|
+
minimum_possible_coverage_exceeded(coverage_setting) if percent && percent > 100
|
304
|
+
end
|
229
305
|
end
|
230
306
|
|
231
307
|
#
|
@@ -235,7 +311,13 @@ module SimpleCov
|
|
235
311
|
# Default is 100% (disabled)
|
236
312
|
#
|
237
313
|
def maximum_coverage_drop(coverage_drop = nil)
|
238
|
-
@maximum_coverage_drop ||=
|
314
|
+
return @maximum_coverage_drop ||= {} unless coverage_drop
|
315
|
+
|
316
|
+
coverage_drop = {primary_coverage => coverage_drop} if coverage_drop.is_a?(Numeric)
|
317
|
+
|
318
|
+
raise_on_invalid_coverage(coverage_drop, "maximum_coverage_drop")
|
319
|
+
|
320
|
+
@maximum_coverage_drop = coverage_drop
|
239
321
|
end
|
240
322
|
|
241
323
|
#
|
@@ -246,15 +328,23 @@ module SimpleCov
|
|
246
328
|
# Default is 0% (disabled)
|
247
329
|
#
|
248
330
|
def minimum_coverage_by_file(coverage = nil)
|
249
|
-
@minimum_coverage_by_file ||=
|
331
|
+
return @minimum_coverage_by_file ||= {} unless coverage
|
332
|
+
|
333
|
+
coverage = {primary_coverage => coverage} if coverage.is_a?(Numeric)
|
334
|
+
|
335
|
+
raise_on_invalid_coverage(coverage, "minimum_coverage_by_file")
|
336
|
+
|
337
|
+
@minimum_coverage_by_file = coverage
|
250
338
|
end
|
251
339
|
|
252
340
|
#
|
253
341
|
# Refuses any coverage drop. That is, coverage is only allowed to increase.
|
254
342
|
# SimpleCov will return non-zero if the coverage decreases.
|
255
343
|
#
|
256
|
-
def refuse_coverage_drop
|
257
|
-
|
344
|
+
def refuse_coverage_drop(*criteria)
|
345
|
+
criteria = coverage_criteria if criteria.empty?
|
346
|
+
|
347
|
+
maximum_coverage_drop(criteria.map { |c| [c, 0] }.to_h)
|
258
348
|
end
|
259
349
|
|
260
350
|
#
|
@@ -287,8 +377,94 @@ module SimpleCov
|
|
287
377
|
groups[group_name] = parse_filter(filter_argument, &filter_proc)
|
288
378
|
end
|
289
379
|
|
380
|
+
SUPPORTED_COVERAGE_CRITERIA = %i[line branch].freeze
|
381
|
+
DEFAULT_COVERAGE_CRITERION = :line
|
382
|
+
#
|
383
|
+
# Define which coverage criterion should be evaluated.
|
384
|
+
#
|
385
|
+
# Possible coverage criteria:
|
386
|
+
# * :line - coverage based on lines aka has this line been executed?
|
387
|
+
# * :branch - coverage based on branches aka has this branch (think conditions) been executed?
|
388
|
+
#
|
389
|
+
# If not set the default is `:line`
|
390
|
+
#
|
391
|
+
# @param [Symbol] criterion
|
392
|
+
#
|
393
|
+
def coverage_criterion(criterion = nil)
|
394
|
+
return @coverage_criterion ||= primary_coverage unless criterion
|
395
|
+
|
396
|
+
raise_if_criterion_unsupported(criterion)
|
397
|
+
|
398
|
+
@coverage_criterion = criterion
|
399
|
+
end
|
400
|
+
|
401
|
+
def enable_coverage(criterion)
|
402
|
+
raise_if_criterion_unsupported(criterion)
|
403
|
+
|
404
|
+
coverage_criteria << criterion
|
405
|
+
end
|
406
|
+
|
407
|
+
def primary_coverage(criterion = nil)
|
408
|
+
if criterion.nil?
|
409
|
+
@primary_coverage ||= DEFAULT_COVERAGE_CRITERION
|
410
|
+
else
|
411
|
+
raise_if_criterion_disabled(criterion)
|
412
|
+
@primary_coverage = criterion
|
413
|
+
end
|
414
|
+
end
|
415
|
+
|
416
|
+
def coverage_criteria
|
417
|
+
@coverage_criteria ||= Set[primary_coverage]
|
418
|
+
end
|
419
|
+
|
420
|
+
def coverage_criterion_enabled?(criterion)
|
421
|
+
coverage_criteria.member?(criterion)
|
422
|
+
end
|
423
|
+
|
424
|
+
def clear_coverage_criteria
|
425
|
+
@coverage_criteria = nil
|
426
|
+
end
|
427
|
+
|
428
|
+
def branch_coverage?
|
429
|
+
branch_coverage_supported? && coverage_criterion_enabled?(:branch)
|
430
|
+
end
|
431
|
+
|
432
|
+
def coverage_start_arguments_supported?
|
433
|
+
# safe to cache as within one process this value should never
|
434
|
+
# change
|
435
|
+
return @coverage_start_arguments_supported if defined?(@coverage_start_arguments_supported)
|
436
|
+
|
437
|
+
@coverage_start_arguments_supported = begin
|
438
|
+
require "coverage"
|
439
|
+
!Coverage.method(:start).arity.zero?
|
440
|
+
end
|
441
|
+
end
|
442
|
+
|
443
|
+
alias branch_coverage_supported? coverage_start_arguments_supported?
|
444
|
+
|
290
445
|
private
|
291
446
|
|
447
|
+
def raise_if_criterion_disabled(criterion)
|
448
|
+
raise_if_criterion_unsupported(criterion)
|
449
|
+
# rubocop:disable Style/IfUnlessModifier
|
450
|
+
unless coverage_criterion_enabled?(criterion)
|
451
|
+
raise "Coverage criterion #{criterion}, is disabled! Please enable it first through enable_coverage #{criterion} (if supported)"
|
452
|
+
end
|
453
|
+
# rubocop:enable Style/IfUnlessModifier
|
454
|
+
end
|
455
|
+
|
456
|
+
def raise_if_criterion_unsupported(criterion)
|
457
|
+
# rubocop:disable Style/IfUnlessModifier
|
458
|
+
unless SUPPORTED_COVERAGE_CRITERIA.member?(criterion)
|
459
|
+
raise "Unsupported coverage criterion #{criterion}, supported values are #{SUPPORTED_COVERAGE_CRITERIA}"
|
460
|
+
end
|
461
|
+
# rubocop:enable Style/IfUnlessModifier
|
462
|
+
end
|
463
|
+
|
464
|
+
def minimum_possible_coverage_exceeded(coverage_option)
|
465
|
+
warn "The coverage you set for #{coverage_option} is greater than 100%"
|
466
|
+
end
|
467
|
+
|
292
468
|
#
|
293
469
|
# The actual filter processor. Not meant for direct use
|
294
470
|
#
|