simplecov 0.16.0 → 0.18.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 +5 -5
- data/CHANGELOG.md +110 -1
- data/CODE_OF_CONDUCT.md +76 -0
- data/LICENSE +20 -0
- data/README.md +281 -112
- data/doc/alternate-formatters.md +10 -0
- data/lib/simplecov.rb +248 -63
- 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 +110 -9
- data/lib/simplecov/coverage_statistics.rb +56 -0
- data/lib/simplecov/defaults.rb +6 -2
- data/lib/simplecov/file_list.rb +66 -13
- data/lib/simplecov/filter.rb +2 -1
- data/lib/simplecov/formatter/multi_formatter.rb +2 -2
- data/lib/simplecov/formatter/simple_formatter.rb +4 -4
- data/lib/simplecov/last_run.rb +3 -1
- data/lib/simplecov/lines_classifier.rb +2 -2
- data/lib/simplecov/profiles.rb +9 -7
- data/lib/simplecov/profiles/hidden_filter.rb +5 -0
- data/lib/simplecov/profiles/rails.rb +1 -1
- data/lib/simplecov/result.rb +39 -6
- data/lib/simplecov/result_adapter.rb +30 -0
- data/lib/simplecov/result_merger.rb +18 -11
- data/lib/simplecov/simulate_coverage.rb +29 -0
- data/lib/simplecov/source_file.rb +227 -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 +16 -0
- data/lib/simplecov/version.rb +1 -1
- metadata +32 -53
- 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
data/doc/alternate-formatters.md
CHANGED
@@ -10,6 +10,11 @@ If you have built or found one that is missing here, please send a Pull Request
|
|
10
10
|
|
11
11
|
A formatter that generates a coverage badge for use in your project's readme using ImageMagick.
|
12
12
|
|
13
|
+
#### [simplecov-small-badge](https://github.com/marcgrimme/simplecov-small-badge)
|
14
|
+
*by Marc Grimme*
|
15
|
+
|
16
|
+
A formatter that generates a small coverage badge for use in your project's readme using the SVG.
|
17
|
+
|
13
18
|
#### [simplecov-cobertura](https://github.com/dashingrocket/simplecov-cobertura)
|
14
19
|
*by Jesse Bowes*
|
15
20
|
|
@@ -49,3 +54,8 @@ A formatter that prints the coverage of the file under test when you run a singl
|
|
49
54
|
*by [Yosuke Kabuto](https://github.com/ysksn)*
|
50
55
|
|
51
56
|
t_wada AA formatter for SimpleCov
|
57
|
+
|
58
|
+
#### [simplecov-material(https://github.com/chiefpansancolt/simplecov-material)
|
59
|
+
*by [Chiefpansancolt](https://github.com/chiefpansancolt)*
|
60
|
+
|
61
|
+
A Material Designed HTML formatter with clean and easy search of files with a tabular left Navigation.
|
data/lib/simplecov.rb
CHANGED
@@ -2,9 +2,6 @@
|
|
2
2
|
|
3
3
|
require "English"
|
4
4
|
|
5
|
-
#
|
6
|
-
# Code coverage for ruby 1.9. Please check out README for a full introduction.
|
7
|
-
#
|
8
5
|
# Coverage may be inaccurate under JRUBY.
|
9
6
|
if defined?(JRUBY_VERSION) && defined?(JRuby)
|
10
7
|
|
@@ -20,6 +17,10 @@ if defined?(JRUBY_VERSION) && defined?(JRuby)
|
|
20
17
|
' or set the "debug.fullTrace=true" option in your .jrubyrc'
|
21
18
|
end
|
22
19
|
end
|
20
|
+
|
21
|
+
#
|
22
|
+
# Code coverage for ruby. Please check out README for a full introduction.
|
23
|
+
#
|
23
24
|
module SimpleCov
|
24
25
|
class << self
|
25
26
|
attr_accessor :running
|
@@ -44,35 +45,49 @@ module SimpleCov
|
|
44
45
|
# Please check out the RDoc for SimpleCov::Configuration to find about available config options
|
45
46
|
#
|
46
47
|
def start(profile = nil, &block)
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
Coverage.start
|
54
|
-
else
|
55
|
-
warn "WARNING: SimpleCov is activated, but you're not running Ruby 1.9+ - no coverage analysis will happen"
|
56
|
-
warn "Starting with SimpleCov 1.0.0, even no-op compatibility with Ruby <= 1.8 will be entirely dropped."
|
57
|
-
false
|
58
|
-
end
|
48
|
+
require "coverage"
|
49
|
+
initial_setup(profile, &block)
|
50
|
+
@result = nil
|
51
|
+
self.pid = Process.pid
|
52
|
+
|
53
|
+
start_coverage_measurement
|
59
54
|
end
|
60
55
|
|
61
56
|
#
|
62
|
-
#
|
63
|
-
#
|
57
|
+
# Collate a series of SimpleCov result files into a single SimpleCov output.
|
58
|
+
# You can optionally specify configuration with a block:
|
59
|
+
# SimpleCov.collate Dir["simplecov-resultset-*/.resultset.json"]
|
60
|
+
# OR
|
61
|
+
# SimpleCov.collate Dir["simplecov-resultset-*/.resultset.json"], 'rails' # using rails profile
|
62
|
+
# OR
|
63
|
+
# SimpleCov.collate Dir["simplecov-resultset-*/.resultset.json"] do
|
64
|
+
# add_filter 'test'
|
65
|
+
# end
|
66
|
+
# OR
|
67
|
+
# SimpleCov.collate Dir["simplecov-resultset-*/.resultset.json"], 'rails' do
|
68
|
+
# add_filter 'test'
|
69
|
+
# end
|
64
70
|
#
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
71
|
+
# Please check out the RDoc for SimpleCov::Configuration to find about
|
72
|
+
# available config options, or checkout the README for more in-depth
|
73
|
+
# information about coverage collation
|
74
|
+
#
|
75
|
+
def collate(result_filenames, profile = nil, &block)
|
76
|
+
raise "There's no reports to be merged" if result_filenames.empty?
|
70
77
|
|
71
|
-
|
78
|
+
initial_setup(profile, &block)
|
79
|
+
|
80
|
+
results = result_filenames.flat_map do |filename|
|
81
|
+
# Re-create each included instance of SimpleCov::Result from the stored run data.
|
82
|
+
(JSON.parse(File.read(filename)) || {}).map do |command_name, coverage|
|
83
|
+
SimpleCov::Result.from_hash(command_name => coverage)
|
72
84
|
end
|
73
85
|
end
|
74
86
|
|
75
|
-
result
|
87
|
+
# Use the ResultMerger to produce a single, merged result, ready to use.
|
88
|
+
@result = SimpleCov::ResultMerger.merge_and_store(*results)
|
89
|
+
|
90
|
+
run_exit_tasks!
|
76
91
|
end
|
77
92
|
|
78
93
|
#
|
@@ -83,13 +98,13 @@ module SimpleCov
|
|
83
98
|
return @result if result?
|
84
99
|
|
85
100
|
# Collect our coverage result
|
86
|
-
|
87
|
-
|
88
|
-
end
|
101
|
+
|
102
|
+
process_coverage_result if running
|
89
103
|
|
90
104
|
# If we're using merging of results, store the current result
|
91
105
|
# first (if there is one), then merge the results and return those
|
92
106
|
if use_merging
|
107
|
+
wait_for_other_processes
|
93
108
|
SimpleCov::ResultMerger.store_result(@result) if result?
|
94
109
|
@result = SimpleCov::ResultMerger.merged_result
|
95
110
|
end
|
@@ -146,22 +161,6 @@ module SimpleCov
|
|
146
161
|
load_profile(name)
|
147
162
|
end
|
148
163
|
|
149
|
-
#
|
150
|
-
# Checks whether we're on a proper version of Ruby (likely 1.9+) which
|
151
|
-
# provides coverage support
|
152
|
-
#
|
153
|
-
def usable?
|
154
|
-
return @usable if defined?(@usable) && !@usable.nil?
|
155
|
-
|
156
|
-
@usable = begin
|
157
|
-
require "coverage"
|
158
|
-
require "simplecov/jruby_fix"
|
159
|
-
true
|
160
|
-
rescue LoadError
|
161
|
-
false
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
164
|
#
|
166
165
|
# Clear out the previously cached .result. Primarily useful in testing
|
167
166
|
#
|
@@ -195,15 +194,22 @@ module SimpleCov
|
|
195
194
|
# Called from at_exit block
|
196
195
|
#
|
197
196
|
def run_exit_tasks!
|
197
|
+
set_exit_exception
|
198
|
+
|
198
199
|
exit_status = SimpleCov.exit_status_from_exception
|
199
200
|
|
200
201
|
SimpleCov.at_exit.call
|
201
202
|
|
202
|
-
|
203
|
+
# Don't modify the exit status unless the result has already been
|
204
|
+
# computed
|
205
|
+
exit_status = SimpleCov.process_result(SimpleCov.result, exit_status) if SimpleCov.result?
|
203
206
|
|
204
207
|
# Force exit with stored status (see github issue #5)
|
205
208
|
# unless it's nil or 0 (see github issue #281)
|
206
|
-
|
209
|
+
if exit_status&.positive?
|
210
|
+
$stderr.printf("SimpleCov failed with exit %<exit_status>d\n", exit_status: exit_status) if print_error_status
|
211
|
+
Kernel.exit exit_status
|
212
|
+
end
|
207
213
|
end
|
208
214
|
|
209
215
|
# @api private
|
@@ -212,32 +218,38 @@ module SimpleCov
|
|
212
218
|
# exit_status = SimpleCov.process_result(SimpleCov.result, exit_status)
|
213
219
|
#
|
214
220
|
def process_result(result, exit_status)
|
215
|
-
return exit_status unless SimpleCov.result? # Result has been computed
|
216
221
|
return exit_status if exit_status != SimpleCov::ExitCodes::SUCCESS # Existing errors
|
217
222
|
|
218
|
-
covered_percent = result.covered_percent.
|
223
|
+
covered_percent = result.covered_percent.floor(2)
|
219
224
|
result_exit_status = result_exit_status(result, covered_percent)
|
220
|
-
if result_exit_status == SimpleCov::ExitCodes::SUCCESS # No result errors
|
221
|
-
|
222
|
-
end
|
223
|
-
result_exit_status
|
225
|
+
write_last_run(covered_percent) if result_exit_status == SimpleCov::ExitCodes::SUCCESS # No result errors
|
226
|
+
final_result_process? ? result_exit_status : SimpleCov::ExitCodes::SUCCESS
|
224
227
|
end
|
225
228
|
|
226
229
|
# @api private
|
227
230
|
#
|
228
231
|
# rubocop:disable Metrics/MethodLength
|
229
232
|
def result_exit_status(result, covered_percent)
|
230
|
-
covered_percentages = result.covered_percentages.map { |percentage| percentage.
|
231
|
-
if
|
232
|
-
|
233
|
+
covered_percentages = result.covered_percentages.map { |percentage| percentage.floor(2) }
|
234
|
+
if (minimum_violations = minimum_coverage_violated(result)).any?
|
235
|
+
report_minimum_violated(minimum_violations)
|
233
236
|
SimpleCov::ExitCodes::MINIMUM_COVERAGE
|
234
237
|
elsif covered_percentages.any? { |p| p < SimpleCov.minimum_coverage_by_file }
|
235
|
-
$stderr.printf(
|
238
|
+
$stderr.printf(
|
239
|
+
"File (%<file>s) is only (%<least_covered_percentage>.2f%%) covered. This is below the expected minimum coverage per file of (%<min_coverage>.2f%%).\n",
|
240
|
+
file: result.least_covered_file,
|
241
|
+
least_covered_percentage: covered_percentages.min,
|
242
|
+
min_coverage: SimpleCov.minimum_coverage_by_file
|
243
|
+
)
|
236
244
|
SimpleCov::ExitCodes::MINIMUM_COVERAGE
|
237
245
|
elsif (last_run = SimpleCov::LastRun.read)
|
238
|
-
coverage_diff = last_run[
|
246
|
+
coverage_diff = last_run[:result][:covered_percent] - covered_percent
|
239
247
|
if coverage_diff > SimpleCov.maximum_coverage_drop
|
240
|
-
$stderr.printf(
|
248
|
+
$stderr.printf(
|
249
|
+
"Coverage has dropped by %<drop_percent>.2f%% since the last time (maximum allowed: %<max_drop>.2f%%).\n",
|
250
|
+
drop_percent: coverage_diff,
|
251
|
+
max_drop: SimpleCov.maximum_coverage_drop
|
252
|
+
)
|
241
253
|
SimpleCov::ExitCodes::MAXIMUM_COVERAGE_DROP
|
242
254
|
else
|
243
255
|
SimpleCov::ExitCodes::SUCCESS
|
@@ -248,20 +260,189 @@ module SimpleCov
|
|
248
260
|
end
|
249
261
|
# rubocop:enable Metrics/MethodLength
|
250
262
|
|
263
|
+
#
|
264
|
+
# @api private
|
265
|
+
#
|
266
|
+
def final_result_process?
|
267
|
+
# checking for ENV["TEST_ENV_NUMBER"] to determine if the tess are being run in parallel
|
268
|
+
!defined?(ParallelTests) || !ENV["TEST_ENV_NUMBER"] || ParallelTests.number_of_running_processes <= 1
|
269
|
+
end
|
270
|
+
|
271
|
+
#
|
272
|
+
# @api private
|
273
|
+
#
|
274
|
+
def wait_for_other_processes
|
275
|
+
return unless defined?(ParallelTests) && final_result_process?
|
276
|
+
|
277
|
+
ParallelTests.wait_for_other_processes_to_finish
|
278
|
+
end
|
279
|
+
|
251
280
|
#
|
252
281
|
# @api private
|
253
282
|
#
|
254
283
|
def write_last_run(covered_percent)
|
255
|
-
SimpleCov::LastRun.write(:
|
284
|
+
SimpleCov::LastRun.write(result: {covered_percent: covered_percent})
|
285
|
+
end
|
286
|
+
|
287
|
+
private
|
288
|
+
|
289
|
+
def initial_setup(profile, &block)
|
290
|
+
load_profile(profile) if profile
|
291
|
+
configure(&block) if block_given?
|
292
|
+
self.running = true
|
293
|
+
end
|
294
|
+
|
295
|
+
#
|
296
|
+
# Trigger Coverage.start depends on given config coverage_criterion
|
297
|
+
#
|
298
|
+
# With Positive branch it supports all coverage measurement types
|
299
|
+
# With Negative branch it supports only line coverage measurement type
|
300
|
+
#
|
301
|
+
def start_coverage_measurement
|
302
|
+
# This blog post gives a good run down of the coverage criterias introduced
|
303
|
+
# in Ruby 2.5: https://blog.bigbinary.com/2018/04/11/ruby-2-5-supports-measuring-branch-and-method-coverages.html
|
304
|
+
# There is also a nice writeup of the different coverage criteria made in this
|
305
|
+
# comment https://github.com/colszowka/simplecov/pull/692#discussion_r281836176 :
|
306
|
+
# Ruby < 2.5:
|
307
|
+
# https://github.com/ruby/ruby/blob/v1_9_3_374/ext/coverage/coverage.c
|
308
|
+
# traditional mode (Array)
|
309
|
+
#
|
310
|
+
# Ruby 2.5:
|
311
|
+
# https://bugs.ruby-lang.org/issues/13901
|
312
|
+
# https://github.com/ruby/ruby/blob/v2_5_3/ext/coverage/coverage.c
|
313
|
+
# default: traditional/compatible mode (Array)
|
314
|
+
# :lines - like traditional mode but using Hash
|
315
|
+
# :branches
|
316
|
+
# :methods
|
317
|
+
# :all - same as lines + branches + methods
|
318
|
+
#
|
319
|
+
# Ruby >= 2.6:
|
320
|
+
# https://bugs.ruby-lang.org/issues/15022
|
321
|
+
# https://github.com/ruby/ruby/blob/v2_6_3/ext/coverage/coverage.c
|
322
|
+
# default: traditional/compatible mode (Array)
|
323
|
+
# :lines - like traditional mode but using Hash
|
324
|
+
# :branches
|
325
|
+
# :methods
|
326
|
+
# :oneshot_lines - can not be combined with lines
|
327
|
+
# :all - same as lines + branches + methods
|
328
|
+
#
|
329
|
+
if coverage_start_arguments_supported?
|
330
|
+
start_coverage_with_criteria
|
331
|
+
else
|
332
|
+
Coverage.start
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
def start_coverage_with_criteria
|
337
|
+
start_arguments = coverage_criteria.map do |criterion|
|
338
|
+
[lookup_corresponding_ruby_coverage_name(criterion), true]
|
339
|
+
end.to_h
|
340
|
+
|
341
|
+
Coverage.start(start_arguments)
|
342
|
+
end
|
343
|
+
|
344
|
+
CRITERION_TO_RUBY_COVERAGE = {
|
345
|
+
branch: :branches,
|
346
|
+
line: :lines
|
347
|
+
}.freeze
|
348
|
+
def lookup_corresponding_ruby_coverage_name(criterion)
|
349
|
+
CRITERION_TO_RUBY_COVERAGE.fetch(criterion)
|
350
|
+
end
|
351
|
+
|
352
|
+
#
|
353
|
+
# Finds files that were to be tracked but were not loaded and initializes
|
354
|
+
# the line-by-line coverage to zero (if relevant) or nil (comments / whitespace etc).
|
355
|
+
#
|
356
|
+
def add_not_loaded_files(result)
|
357
|
+
if tracked_files
|
358
|
+
result = result.dup
|
359
|
+
Dir[tracked_files].each do |file|
|
360
|
+
absolute_path = File.expand_path(file)
|
361
|
+
result[absolute_path] ||= SimulateCoverage.call(absolute_path)
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
365
|
+
result
|
366
|
+
end
|
367
|
+
|
368
|
+
#
|
369
|
+
# Call steps that handle process coverage result
|
370
|
+
#
|
371
|
+
# @return [Hash]
|
372
|
+
#
|
373
|
+
def process_coverage_result
|
374
|
+
adapt_coverage_result
|
375
|
+
remove_useless_results
|
376
|
+
result_with_not_loaded_files
|
377
|
+
end
|
378
|
+
|
379
|
+
#
|
380
|
+
# Unite the result so it wouldn't matter what coverage type was called
|
381
|
+
#
|
382
|
+
# @return [Hash]
|
383
|
+
#
|
384
|
+
def adapt_coverage_result
|
385
|
+
@result = SimpleCov::ResultAdapter.call(Coverage.result)
|
386
|
+
end
|
387
|
+
|
388
|
+
#
|
389
|
+
# Filter coverage result
|
390
|
+
# The result before filter also has result of coverage for files
|
391
|
+
# are not related to the project like loaded gems coverage.
|
392
|
+
#
|
393
|
+
# @return [Hash]
|
394
|
+
#
|
395
|
+
def remove_useless_results
|
396
|
+
@result = SimpleCov::UselessResultsRemover.call(@result)
|
397
|
+
end
|
398
|
+
|
399
|
+
#
|
400
|
+
# Initialize result with files that are not included by coverage
|
401
|
+
# and added inside the config block
|
402
|
+
#
|
403
|
+
# @return [Hash]
|
404
|
+
#
|
405
|
+
def result_with_not_loaded_files
|
406
|
+
@result = SimpleCov::Result.new(add_not_loaded_files(@result))
|
407
|
+
end
|
408
|
+
|
409
|
+
def minimum_coverage_violated(result)
|
410
|
+
coverage_achieved = minimum_coverage.map do |criterion, percent|
|
411
|
+
{
|
412
|
+
criterion: criterion,
|
413
|
+
minimum_expected: percent,
|
414
|
+
actual: result.coverage_statistics[criterion].percent
|
415
|
+
}
|
416
|
+
end
|
417
|
+
|
418
|
+
coverage_achieved.select do |achieved|
|
419
|
+
achieved.fetch(:actual) < achieved.fetch(:minimum_expected)
|
420
|
+
end
|
421
|
+
end
|
422
|
+
|
423
|
+
def report_minimum_violated(violations)
|
424
|
+
violations.each do |violation|
|
425
|
+
$stderr.printf(
|
426
|
+
"%<criterion>s coverage (%<covered>.2f%%) is below the expected minimum coverage (%<minimum_coverage>.2f%%).\n",
|
427
|
+
covered: violation.fetch(:actual).floor(2),
|
428
|
+
minimum_coverage: violation.fetch(:minimum_expected),
|
429
|
+
criterion: violation.fetch(:criterion).capitalize
|
430
|
+
)
|
431
|
+
end
|
256
432
|
end
|
257
433
|
end
|
258
434
|
end
|
259
435
|
|
260
436
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__)))
|
437
|
+
require "set"
|
438
|
+
require "forwardable"
|
261
439
|
require "simplecov/configuration"
|
262
|
-
SimpleCov.
|
440
|
+
SimpleCov.extend SimpleCov::Configuration
|
441
|
+
require "simplecov/coverage_statistics"
|
263
442
|
require "simplecov/exit_codes"
|
264
443
|
require "simplecov/profiles"
|
444
|
+
require "simplecov/source_file/line"
|
445
|
+
require "simplecov/source_file/branch"
|
265
446
|
require "simplecov/source_file"
|
266
447
|
require "simplecov/file_list"
|
267
448
|
require "simplecov/result"
|
@@ -269,13 +450,17 @@ require "simplecov/filter"
|
|
269
450
|
require "simplecov/formatter"
|
270
451
|
require "simplecov/last_run"
|
271
452
|
require "simplecov/lines_classifier"
|
272
|
-
require "simplecov/raw_coverage"
|
273
453
|
require "simplecov/result_merger"
|
274
454
|
require "simplecov/command_guesser"
|
275
455
|
require "simplecov/version"
|
456
|
+
require "simplecov/result_adapter"
|
457
|
+
require "simplecov/combine"
|
458
|
+
require "simplecov/combine/branches_combiner"
|
459
|
+
require "simplecov/combine/files_combiner"
|
460
|
+
require "simplecov/combine/lines_combiner"
|
461
|
+
require "simplecov/combine/results_combiner"
|
462
|
+
require "simplecov/useless_results_remover"
|
463
|
+
require "simplecov/simulate_coverage"
|
276
464
|
|
277
465
|
# Load default config
|
278
466
|
require "simplecov/defaults" unless ENV["SIMPLECOV_NO_DEFAULTS"]
|
279
|
-
|
280
|
-
# Load Rails integration (only for Rails 3, see #113)
|
281
|
-
require "simplecov/railtie" if defined? Rails::Railtie
|
@@ -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 throught his interface,
|
13
|
+
# as it takes care of short circuting 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
|