simplecov 0.22.0 → 1.1.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/LICENSE +1 -1
- data/README.md +71 -916
- data/exe/simplecov +11 -0
- data/lib/minitest/simplecov_plugin.rb +13 -5
- data/lib/simplecov/atomic_file.rb +70 -0
- data/lib/simplecov/autostart.rb +11 -0
- data/lib/simplecov/cli/clean.rb +87 -0
- data/lib/simplecov/cli/command_helpers.rb +55 -0
- data/lib/simplecov/cli/coverage.rb +86 -0
- data/lib/simplecov/cli/coverage_file.rb +65 -0
- data/lib/simplecov/cli/diff.rb +147 -0
- data/lib/simplecov/cli/dotfile.rb +111 -0
- data/lib/simplecov/cli/merge.rb +120 -0
- data/lib/simplecov/cli/open.rb +48 -0
- data/lib/simplecov/cli/report.rb +97 -0
- data/lib/simplecov/cli/run.rb +36 -0
- data/lib/simplecov/cli/serve/report_preparer.rb +29 -0
- data/lib/simplecov/cli/serve/static_file_handler.rb +122 -0
- data/lib/simplecov/cli/serve.rb +85 -0
- data/lib/simplecov/cli/uncovered.rb +103 -0
- data/lib/simplecov/cli.rb +163 -0
- data/lib/simplecov/color.rb +83 -0
- data/lib/simplecov/combine/branches_combiner.rb +54 -7
- data/lib/simplecov/combine/coverage_accumulator.rb +268 -0
- data/lib/simplecov/combine/identity_interner.rb +30 -0
- data/lib/simplecov/combine/interned_counts.rb +30 -0
- data/lib/simplecov/combine/lines_combiner.rb +53 -23
- data/lib/simplecov/combine/methods_combiner.rb +74 -0
- data/lib/simplecov/combine/results_combiner.rb +13 -36
- data/lib/simplecov/combine.rb +5 -23
- data/lib/simplecov/command_guesser.rb +104 -33
- data/lib/simplecov/configuration/coverage.rb +172 -0
- data/lib/simplecov/configuration/coverage_criteria.rb +154 -0
- data/lib/simplecov/configuration/eval_coverage.rb +41 -0
- data/lib/simplecov/configuration/filters.rb +164 -0
- data/lib/simplecov/configuration/formatting.rb +138 -0
- data/lib/simplecov/configuration/groups.rb +42 -0
- data/lib/simplecov/configuration/ignored_entries.rb +63 -0
- data/lib/simplecov/configuration/merging.rb +165 -0
- data/lib/simplecov/configuration/thresholds.rb +179 -0
- data/lib/simplecov/configuration.rb +83 -420
- data/lib/simplecov/coverage_json.rb +24 -0
- data/lib/simplecov/coverage_statistics.rb +16 -10
- data/lib/simplecov/coverage_violations.rb +159 -0
- data/lib/simplecov/defaults.rb +34 -23
- data/lib/simplecov/deprecation.rb +45 -0
- data/lib/simplecov/directive.rb +167 -0
- data/lib/simplecov/exit_codes/check.rb +33 -0
- data/lib/simplecov/exit_codes/exit_code_handling.rb +8 -2
- data/lib/simplecov/exit_codes/maximum_coverage_drop_check.rb +18 -65
- data/lib/simplecov/exit_codes/maximum_overall_coverage_check.rb +32 -0
- data/lib/simplecov/exit_codes/minimum_coverage_by_file_check.rb +17 -36
- data/lib/simplecov/exit_codes/minimum_coverage_by_group_check.rb +30 -0
- data/lib/simplecov/exit_codes/minimum_overall_coverage_check.rb +37 -33
- data/lib/simplecov/exit_codes.rb +20 -0
- data/lib/simplecov/exit_handling.rb +128 -0
- data/lib/simplecov/file_list.rb +70 -24
- data/lib/simplecov/filter.rb +105 -26
- data/lib/simplecov/formatter/base.rb +118 -0
- data/lib/simplecov/formatter/coverage_json_writer.rb +97 -0
- data/lib/simplecov/formatter/html_formatter/public/index.html +87 -0
- data/lib/simplecov/formatter/html_formatter/viewer_data_validator.rb +96 -0
- data/lib/simplecov/formatter/html_formatter.rb +105 -0
- data/lib/simplecov/formatter/json_formatter/errors_formatter.rb +88 -0
- data/lib/simplecov/formatter/json_formatter/result_hash_formatter.rb +118 -0
- data/lib/simplecov/formatter/json_formatter/source_file_formatter.rb +93 -0
- data/lib/simplecov/formatter/json_formatter.rb +46 -0
- data/lib/simplecov/formatter/multi_formatter.rb +12 -8
- data/lib/simplecov/formatter/simple_formatter.rb +14 -11
- data/lib/simplecov/formatter.rb +16 -0
- data/lib/simplecov/group_names.rb +32 -0
- data/lib/simplecov/last_run.rb +18 -4
- data/lib/simplecov/lines_classifier.rb +48 -15
- data/lib/simplecov/load_global_config.rb +12 -4
- data/lib/simplecov/parallel_adapters/base.rb +78 -0
- data/lib/simplecov/parallel_adapters/generic.rb +45 -0
- data/lib/simplecov/parallel_adapters/parallel_tests.rb +93 -0
- data/lib/simplecov/parallel_adapters.rb +85 -0
- data/lib/simplecov/parallel_coordination.rb +134 -0
- data/lib/simplecov/parallel_result_merger.rb +230 -0
- data/lib/simplecov/process.rb +52 -12
- data/lib/simplecov/profiles/bundler_filter.rb +1 -1
- data/lib/simplecov/profiles/hidden_filter.rb +1 -1
- data/lib/simplecov/profiles/rails.rb +24 -10
- data/lib/simplecov/profiles/root_filter.rb +6 -5
- data/lib/simplecov/profiles/strict.rb +32 -0
- data/lib/simplecov/profiles/test_frameworks.rb +1 -4
- data/lib/simplecov/profiles.rb +32 -3
- data/lib/simplecov/report_deferral.rb +49 -0
- data/lib/simplecov/report_stamp.rb +28 -0
- data/lib/simplecov/result/missing_source_files_reporter.rb +49 -0
- data/lib/simplecov/result/source_file_builder.rb +51 -0
- data/lib/simplecov/result.rb +145 -26
- data/lib/simplecov/result_adapter.rb +139 -8
- data/lib/simplecov/result_merger/legacy_format_adapter.rb +28 -0
- data/lib/simplecov/result_merger/resultset_file.rb +74 -0
- data/lib/simplecov/result_merger/resultset_run_identity.rb +67 -0
- data/lib/simplecov/result_merger/resultset_store.rb +53 -0
- data/lib/simplecov/result_merger/unloaded_files.rb +103 -0
- data/lib/simplecov/result_merger.rb +109 -114
- data/lib/simplecov/result_processing.rb +218 -0
- data/lib/simplecov/run_identity.rb +77 -0
- data/lib/simplecov/simulate_coverage.rb +83 -12
- data/lib/simplecov/source_file/branch.rb +1 -3
- data/lib/simplecov/source_file/branch_builder.rb +114 -0
- data/lib/simplecov/source_file/builder_context.rb +28 -0
- data/lib/simplecov/source_file/line.rb +9 -4
- data/lib/simplecov/source_file/line_builder.rb +43 -0
- data/lib/simplecov/source_file/method.rb +58 -0
- data/lib/simplecov/source_file/method_builder.rb +60 -0
- data/lib/simplecov/source_file/ruby_data_parser.rb +110 -0
- data/lib/simplecov/source_file/skip_chunks.rb +72 -0
- data/lib/simplecov/source_file/source_loader.rb +79 -0
- data/lib/simplecov/source_file/statistics.rb +65 -0
- data/lib/simplecov/source_file.rb +66 -232
- data/lib/simplecov/static_coverage_extractor/condition_folding.rb +239 -0
- data/lib/simplecov/static_coverage_extractor/location_conventions.rb +236 -0
- data/lib/simplecov/static_coverage_extractor/method_collector.rb +62 -0
- data/lib/simplecov/static_coverage_extractor/prism_compat.rb +55 -0
- data/lib/simplecov/static_coverage_extractor/value_position.rb +74 -0
- data/lib/simplecov/static_coverage_extractor/visitor.rb +183 -0
- data/lib/simplecov/static_coverage_extractor.rb +110 -0
- data/lib/simplecov/unloaded_file_injector.rb +75 -0
- data/lib/simplecov/useless_results_remover.rb +16 -7
- data/lib/simplecov/version.rb +1 -1
- data/lib/simplecov-html.rb +4 -0
- data/lib/simplecov.rb +185 -380
- data/lib/simplecov_json_formatter.rb +4 -0
- data/sig/simplecov.rbs +1777 -0
- metadata +111 -62
- data/CHANGELOG.md +0 -191
- data/doc/alternate-formatters.md +0 -71
- data/doc/commercial-services.md +0 -25
- data/doc/editor-integration.md +0 -18
- data/lib/simplecov/combine/files_combiner.rb +0 -24
- data/lib/simplecov/default_formatter.rb +0 -20
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SimpleCov
|
|
4
|
+
# Result merging and subprocess / parallel-test coordination:
|
|
5
|
+
# `merging`, `merge_subprocesses`, `merge_timeout`, `parallel_tests`.
|
|
6
|
+
module Configuration
|
|
7
|
+
#
|
|
8
|
+
# Get or set whether SimpleCov should hook `Process._fork` to
|
|
9
|
+
# attach itself to subprocesses. Required when the suite uses
|
|
10
|
+
# parallel test workers (e.g. Rails' `parallelize(workers:)`).
|
|
11
|
+
# Defaults to false.
|
|
12
|
+
#
|
|
13
|
+
def merge_subprocesses(value = nil)
|
|
14
|
+
return @enable_for_subprocesses if defined?(@enable_for_subprocesses) && value.nil?
|
|
15
|
+
|
|
16
|
+
@enable_for_subprocesses = value || false
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# @api private — predicate used by `start_tracking` to decide
|
|
20
|
+
# whether to install the fork hook.
|
|
21
|
+
def enabled_for_subprocesses?
|
|
22
|
+
defined?(@enable_for_subprocesses) ? @enable_for_subprocesses : false
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
#
|
|
26
|
+
# Get or set whether SimpleCov should auto-require the
|
|
27
|
+
# `parallel_tests` gem when it sees `TEST_ENV_NUMBER` /
|
|
28
|
+
# `PARALLEL_TEST_GROUPS` in the environment. Defaults to auto-detect
|
|
29
|
+
# (nil). See #1018.
|
|
30
|
+
#
|
|
31
|
+
def parallel_tests(value = :__no_arg__)
|
|
32
|
+
return defined?(@parallel_tests) ? @parallel_tests : nil if value == :__no_arg__
|
|
33
|
+
|
|
34
|
+
@parallel_tests = value
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# DEPRECATED: alias for `merge_subprocesses`. Same value/behavior.
|
|
38
|
+
def enable_for_subprocesses(value = nil)
|
|
39
|
+
SimpleCov::Deprecation.warn("`SimpleCov.enable_for_subprocesses` is deprecated. " \
|
|
40
|
+
"Replace with `SimpleCov.merge_subprocesses` (same value, same behavior).")
|
|
41
|
+
merge_subprocesses(value)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
#
|
|
45
|
+
# Get or set whether to merge results from multiple test suites
|
|
46
|
+
# (test:units, test:functionals, cucumber, ...) into a single
|
|
47
|
+
# coverage report. Defaults to true.
|
|
48
|
+
#
|
|
49
|
+
def merging(use = nil)
|
|
50
|
+
@use_merging = use unless use.nil?
|
|
51
|
+
@use_merging = true unless defined?(@use_merging) && @use_merging == false
|
|
52
|
+
@use_merging
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
#
|
|
56
|
+
# Get or set whether SimpleCov's selected final process owns merge processing:
|
|
57
|
+
# waiting for sibling workers, building the merged result, formatting,
|
|
58
|
+
# enforcing thresholds, and writing `.last_run.json`.
|
|
59
|
+
#
|
|
60
|
+
# Defaults to true, except for recognized multi-worker parallel runs
|
|
61
|
+
# that explicitly write to a custom coverage destination while merging
|
|
62
|
+
# is enabled. Those runs are likely using an external `SimpleCov.collate`
|
|
63
|
+
# step to finalize the merge.
|
|
64
|
+
#
|
|
65
|
+
def finalize_merge(value = :__no_arg__)
|
|
66
|
+
unless value == :__no_arg__
|
|
67
|
+
@finalize_merge = value
|
|
68
|
+
@finalize_merge_explicit = true
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
return @finalize_merge if defined?(@finalize_merge_explicit) && @finalize_merge_explicit
|
|
72
|
+
|
|
73
|
+
inferred = inferred_finalize_merge?
|
|
74
|
+
warn_about_inferred_finalize_merge unless inferred
|
|
75
|
+
inferred
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def finalize_merge?
|
|
79
|
+
finalize_merge
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# @api private
|
|
83
|
+
def merge_finalization_owner?
|
|
84
|
+
collating_result? || (finalize_merge? && final_result_process?)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# DEPRECATED: alias for `merging`. Same value, same behavior.
|
|
88
|
+
# Delegating (rather than duplicating the body) also fixes the
|
|
89
|
+
# return value: this used to return nil where `merging` returns
|
|
90
|
+
# false, because the final expression was the skipped guard
|
|
91
|
+
# assignment rather than the stored value.
|
|
92
|
+
def use_merging(use = nil)
|
|
93
|
+
SimpleCov::Deprecation.warn("`SimpleCov.use_merging` is deprecated. " \
|
|
94
|
+
"Replace with `SimpleCov.merging` (same value, same behavior).")
|
|
95
|
+
merging(use)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
#
|
|
99
|
+
# Defines the maximum age (in seconds) of a resultset to still be
|
|
100
|
+
# included in merged results. Default is 600 seconds (10 minutes).
|
|
101
|
+
#
|
|
102
|
+
def merge_timeout(seconds = nil)
|
|
103
|
+
@merge_timeout = seconds if seconds.is_a?(Integer)
|
|
104
|
+
@merge_timeout ||= 600
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
#
|
|
108
|
+
# Defines how long (in seconds) the reporting process waits for the
|
|
109
|
+
# remaining parallel-test workers to write their resultsets before it
|
|
110
|
+
# proceeds with a partial merge. Default is 60 seconds. Raise it when a
|
|
111
|
+
# slow worker routinely finishes well after the others, so its coverage
|
|
112
|
+
# is still included and the minimum / maximum coverage checks aren't
|
|
113
|
+
# skipped against a partial total.
|
|
114
|
+
#
|
|
115
|
+
def parallel_wait_timeout(seconds = nil)
|
|
116
|
+
@parallel_wait_timeout = seconds if seconds.is_a?(Integer)
|
|
117
|
+
@parallel_wait_timeout ||= 60
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
private
|
|
121
|
+
|
|
122
|
+
def inferred_finalize_merge?
|
|
123
|
+
return true unless merging
|
|
124
|
+
|
|
125
|
+
adapter = SimpleCov::ParallelAdapters.current
|
|
126
|
+
return true unless adapter
|
|
127
|
+
return true unless adapter.expected_worker_count > 1
|
|
128
|
+
return true unless parallel_worker_environment?
|
|
129
|
+
return true unless explicit_custom_coverage_destination?
|
|
130
|
+
|
|
131
|
+
false
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def parallel_worker_environment?
|
|
135
|
+
ENV.key?("TEST_ENV_NUMBER") || ENV.key?("PARALLEL_TEST_GROUPS")
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def explicit_custom_coverage_destination?
|
|
139
|
+
return false unless explicit_coverage_destination?
|
|
140
|
+
|
|
141
|
+
coverage_path != File.expand_path("coverage", root)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def explicit_coverage_destination?
|
|
145
|
+
(defined?(@coverage_path_explicit) && @coverage_path_explicit) ||
|
|
146
|
+
(defined?(@coverage_dir_explicit) && @coverage_dir_explicit)
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def warn_about_inferred_finalize_merge
|
|
150
|
+
return if defined?(@finalize_merge_inference_warned) && @finalize_merge_inference_warned
|
|
151
|
+
return unless print_errors
|
|
152
|
+
|
|
153
|
+
@finalize_merge_inference_warned = true
|
|
154
|
+
warn SimpleCov::Color.colorize(inferred_finalize_merge_warning, :yellow)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def inferred_finalize_merge_warning
|
|
158
|
+
"SimpleCov inferred `finalize_merge false` because this parallel worker is merging " \
|
|
159
|
+
"into a custom coverage destination. Set `SimpleCov.finalize_merge false` to keep " \
|
|
160
|
+
"external collation ownership, or `SimpleCov.finalize_merge true` if this worker " \
|
|
161
|
+
"should wait, merge, format, enforce thresholds, and write `.last_run.json`. " \
|
|
162
|
+
"See https://github.com/simplecov-ruby/simplecov#merge-finalization-ownership."
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
end
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SimpleCov
|
|
4
|
+
# Coverage threshold configuration: `minimum_coverage`,
|
|
5
|
+
# `maximum_coverage`, `expected_coverage`, `maximum_coverage_drop`,
|
|
6
|
+
# `minimum_coverage_by_file`, `minimum_coverage_by_group`,
|
|
7
|
+
# `refuse_coverage_drop`, and friends.
|
|
8
|
+
module Configuration
|
|
9
|
+
#
|
|
10
|
+
# Defines the minimum overall coverage required for the testsuite to pass.
|
|
11
|
+
# Returns non-zero if the current coverage is below this threshold.
|
|
12
|
+
# Default is 0% (disabled).
|
|
13
|
+
#
|
|
14
|
+
def minimum_coverage(coverage = nil)
|
|
15
|
+
return @minimum_coverage ||= {} unless coverage
|
|
16
|
+
|
|
17
|
+
@minimum_coverage = normalized_threshold(coverage, "minimum_coverage")
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def raise_on_invalid_coverage(coverage, coverage_setting)
|
|
21
|
+
coverage.each_key { |criterion| raise_if_criterion_disabled(criterion) }
|
|
22
|
+
coverage.each_value do |percent|
|
|
23
|
+
minimum_possible_coverage_exceeded(coverage_setting) if percent && percent > 100
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
#
|
|
28
|
+
# Defines the maximum overall coverage allowed for the testsuite to
|
|
29
|
+
# pass. Useful paired with `minimum_coverage` (or via
|
|
30
|
+
# `expected_coverage`) to pin coverage to an exact value, so an
|
|
31
|
+
# unexpected jump up fails the build. See #187.
|
|
32
|
+
#
|
|
33
|
+
def maximum_coverage(coverage = nil)
|
|
34
|
+
return @maximum_coverage ||= {} unless coverage
|
|
35
|
+
|
|
36
|
+
@maximum_coverage = normalized_threshold(coverage, "maximum_coverage")
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
#
|
|
40
|
+
# Pins the suite to an exact coverage figure by setting both
|
|
41
|
+
# `minimum_coverage` and `maximum_coverage`. See #187.
|
|
42
|
+
#
|
|
43
|
+
def expected_coverage(coverage = nil)
|
|
44
|
+
return minimum_coverage if coverage.nil?
|
|
45
|
+
|
|
46
|
+
minimum_coverage(coverage)
|
|
47
|
+
maximum_coverage(coverage)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
#
|
|
51
|
+
# Defines the maximum coverage drop at once allowed for the
|
|
52
|
+
# testsuite to pass. Default is 100% (disabled).
|
|
53
|
+
#
|
|
54
|
+
def maximum_coverage_drop(coverage_drop = nil)
|
|
55
|
+
return @maximum_coverage_drop ||= {} unless coverage_drop
|
|
56
|
+
|
|
57
|
+
@maximum_coverage_drop = normalized_threshold(coverage_drop, "maximum_coverage_drop")
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
#
|
|
61
|
+
# Defines the minimum coverage per file required for the testsuite
|
|
62
|
+
# to pass. Accepts a Numeric (global threshold on the primary
|
|
63
|
+
# criterion), a Symbol-keyed Hash (per-criterion globals), or a
|
|
64
|
+
# Hash mixing Symbol keys with String / Regexp keys to declare
|
|
65
|
+
# per-path overrides. See README and #575.
|
|
66
|
+
#
|
|
67
|
+
def minimum_coverage_by_file(coverage = nil)
|
|
68
|
+
return @minimum_coverage_by_file ||= {} unless coverage
|
|
69
|
+
|
|
70
|
+
coverage = {primary_coverage => coverage} if coverage.is_a?(Numeric)
|
|
71
|
+
defaults, overrides = partition_per_file_thresholds(coverage)
|
|
72
|
+
|
|
73
|
+
SimpleCov::Deprecation.warn("`SimpleCov.minimum_coverage_by_file` is deprecated. " \
|
|
74
|
+
"Replace it with:\n#{per_file_coverage_replacement(defaults, overrides)}")
|
|
75
|
+
|
|
76
|
+
raise_on_invalid_coverage(defaults, "minimum_coverage_by_file")
|
|
77
|
+
overrides.each_value { |criteria| raise_on_invalid_coverage(criteria, "minimum_coverage_by_file") }
|
|
78
|
+
|
|
79
|
+
@minimum_coverage_by_file = defaults
|
|
80
|
+
@minimum_coverage_by_file_overrides = overrides
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Returns the per-path overrides set via `minimum_coverage_by_file`.
|
|
84
|
+
def minimum_coverage_by_file_overrides
|
|
85
|
+
@minimum_coverage_by_file_overrides ||= {}
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
#
|
|
89
|
+
# Defines the minimum coverage per group required for the testsuite
|
|
90
|
+
# to pass. Default is 0% (disabled).
|
|
91
|
+
#
|
|
92
|
+
def minimum_coverage_by_group(coverage = nil)
|
|
93
|
+
return @minimum_coverage_by_group ||= {} unless coverage
|
|
94
|
+
|
|
95
|
+
SimpleCov::Deprecation.warn("`SimpleCov.minimum_coverage_by_group` is deprecated. " \
|
|
96
|
+
"Replace it with:\n#{per_group_coverage_replacement(coverage)}")
|
|
97
|
+
@minimum_coverage_by_group = coverage.to_h do |group_name, group_coverage|
|
|
98
|
+
[GroupNames.normalize(group_name), normalized_threshold(group_coverage, "minimum_coverage_by_group")]
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
#
|
|
103
|
+
# Refuses any coverage drop. Coverage is only allowed to increase.
|
|
104
|
+
#
|
|
105
|
+
def refuse_coverage_drop(*criteria)
|
|
106
|
+
criteria = coverage_criteria if criteria.empty?
|
|
107
|
+
maximum_coverage_drop(criteria.to_h { |c| [c, 0] })
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
private
|
|
111
|
+
|
|
112
|
+
# Shared normalize-and-validate step behind every threshold setter:
|
|
113
|
+
# a bare Numeric targets the primary criterion, and the resulting
|
|
114
|
+
# per-criterion hash is validated before it is stored.
|
|
115
|
+
def normalized_threshold(coverage, setting)
|
|
116
|
+
coverage = {primary_coverage => coverage} if coverage.is_a?(Numeric)
|
|
117
|
+
raise_on_invalid_coverage(coverage, setting)
|
|
118
|
+
coverage
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# Split a `minimum_coverage_by_file` argument into Symbol-keyed
|
|
122
|
+
# criterion defaults and String/Regexp-keyed per-path overrides;
|
|
123
|
+
# normalize Numeric override values to `{primary_coverage => N}`
|
|
124
|
+
# so downstream code only has one shape to handle.
|
|
125
|
+
def partition_per_file_thresholds(coverage)
|
|
126
|
+
coverage.each_key { |key| validate_per_file_key(key) }
|
|
127
|
+
pairs = coverage.partition { |key, _| key.is_a?(Symbol) }
|
|
128
|
+
# The assertions restate what the partition predicate guarantees:
|
|
129
|
+
# Symbol keys carry per-criterion Numeric defaults, the rest are paths.
|
|
130
|
+
defaults = pairs[0].to_h #: coverage_thresholds
|
|
131
|
+
raw = pairs[1].to_h #: Hash[String | Regexp, Numeric | coverage_thresholds]
|
|
132
|
+
overrides = raw.transform_values { |value| value.is_a?(Numeric) ? {primary_coverage => value} : value }
|
|
133
|
+
[defaults, overrides]
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def validate_per_file_key(key)
|
|
137
|
+
return if key.is_a?(Symbol) || key.is_a?(String) || key.is_a?(Regexp)
|
|
138
|
+
|
|
139
|
+
raise SimpleCov::ConfigurationError,
|
|
140
|
+
"minimum_coverage_by_file keys must be Symbol (criterion), String, or Regexp; got #{key.inspect}"
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def minimum_possible_coverage_exceeded(coverage_option)
|
|
144
|
+
warn "The coverage you set for #{coverage_option} is greater than 100%"
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# Render the `coverage` configuration equivalent to a (deprecated)
|
|
148
|
+
# `minimum_coverage_by_file` argument so the deprecation warning can be
|
|
149
|
+
# copy-pasted verbatim into the user's config.
|
|
150
|
+
def per_file_coverage_replacement(defaults, overrides)
|
|
151
|
+
by_criterion = {} #: Hash[Symbol, Array[String]]
|
|
152
|
+
defaults.each { |criterion, percent| (by_criterion[criterion] ||= []) << "minimum_per_file #{percent}" }
|
|
153
|
+
overrides.each do |target, criteria|
|
|
154
|
+
criteria.each do |criterion, percent|
|
|
155
|
+
(by_criterion[criterion] ||= []) << "minimum_per_file #{percent}, only: #{target.inspect}"
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
render_coverage_blocks(by_criterion)
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
# Same, for a (deprecated) `minimum_coverage_by_group` argument.
|
|
162
|
+
def per_group_coverage_replacement(coverage)
|
|
163
|
+
by_criterion = {} #: Hash[Symbol, Array[String]]
|
|
164
|
+
coverage.each do |group_name, thresholds|
|
|
165
|
+
normalized = (thresholds.is_a?(Numeric) ? {primary_coverage => thresholds} : thresholds) #: coverage_thresholds
|
|
166
|
+
normalized.each do |criterion, percent|
|
|
167
|
+
(by_criterion[criterion] ||= []) << "minimum_per_group #{percent}, only: #{group_name.inspect}"
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
render_coverage_blocks(by_criterion)
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def render_coverage_blocks(by_criterion)
|
|
174
|
+
by_criterion.map do |criterion, statements|
|
|
175
|
+
" coverage(#{criterion.inspect}) { #{statements.join('; ')} }"
|
|
176
|
+
end.join("\n")
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|