simplecov 0.22.0 → 1.0.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/LICENSE +1 -1
- data/README.md +1058 -508
- data/doc/alternate-formatters.md +0 -5
- data/doc/commercial-services.md +5 -5
- data/exe/simplecov +11 -0
- data/lib/minitest/simplecov_plugin.rb +13 -5
- data/lib/simplecov/autostart.rb +11 -0
- data/lib/simplecov/cli/clean.rb +47 -0
- data/lib/simplecov/cli/coverage.rb +91 -0
- data/lib/simplecov/cli/diff.rb +151 -0
- data/lib/simplecov/cli/dotfile.rb +100 -0
- data/lib/simplecov/cli/merge.rb +116 -0
- data/lib/simplecov/cli/open.rb +50 -0
- data/lib/simplecov/cli/report.rb +84 -0
- data/lib/simplecov/cli/run.rb +36 -0
- data/lib/simplecov/cli/serve.rb +139 -0
- data/lib/simplecov/cli/uncovered.rb +107 -0
- data/lib/simplecov/cli.rb +150 -0
- data/lib/simplecov/color.rb +74 -0
- data/lib/simplecov/combine/branches_combiner.rb +27 -5
- data/lib/simplecov/combine/files_combiner.rb +7 -1
- data/lib/simplecov/combine/lines_combiner.rb +19 -17
- data/lib/simplecov/combine/methods_combiner.rb +26 -0
- data/lib/simplecov/combine/results_combiner.rb +5 -4
- data/lib/simplecov/command_guesser.rb +46 -32
- data/lib/simplecov/configuration/coverage.rb +171 -0
- data/lib/simplecov/configuration/coverage_criteria.rb +156 -0
- data/lib/simplecov/configuration/filters.rb +197 -0
- data/lib/simplecov/configuration/formatting.rb +119 -0
- data/lib/simplecov/configuration/ignored_entries.rb +63 -0
- data/lib/simplecov/configuration/merging.rb +164 -0
- data/lib/simplecov/configuration/thresholds.rb +174 -0
- data/lib/simplecov/configuration.rb +91 -407
- data/lib/simplecov/coverage_statistics.rb +12 -9
- data/lib/simplecov/coverage_violations.rb +148 -0
- data/lib/simplecov/defaults.rb +27 -20
- data/lib/simplecov/deprecation.rb +45 -0
- data/lib/simplecov/directive.rb +162 -0
- data/lib/simplecov/exit_codes/exit_code_handling.rb +8 -2
- data/lib/simplecov/exit_codes/maximum_coverage_drop_check.rb +19 -57
- data/lib/simplecov/exit_codes/maximum_overall_coverage_check.rb +45 -0
- data/lib/simplecov/exit_codes/minimum_coverage_by_file_check.rb +17 -27
- data/lib/simplecov/exit_codes/minimum_coverage_by_group_check.rb +41 -0
- data/lib/simplecov/exit_codes/minimum_overall_coverage_check.rb +38 -21
- data/lib/simplecov/exit_codes.rb +3 -0
- data/lib/simplecov/exit_handling.rb +158 -0
- data/lib/simplecov/file_list.rb +61 -17
- data/lib/simplecov/filter.rb +69 -24
- data/lib/simplecov/formatter/base.rb +101 -0
- data/lib/simplecov/formatter/html_formatter/public/application.css +1 -0
- data/lib/simplecov/formatter/html_formatter/public/application.js +18 -0
- data/lib/simplecov/formatter/html_formatter/public/favicon_green.png +0 -0
- data/lib/simplecov/formatter/html_formatter/public/favicon_red.png +0 -0
- data/lib/simplecov/formatter/html_formatter/public/favicon_yellow.png +0 -0
- data/lib/simplecov/formatter/html_formatter/public/index.html +56 -0
- data/lib/simplecov/formatter/html_formatter.rb +79 -0
- data/lib/simplecov/formatter/json_formatter/errors_formatter.rb +84 -0
- data/lib/simplecov/formatter/json_formatter/result_hash_formatter.rb +128 -0
- data/lib/simplecov/formatter/json_formatter/source_file_formatter.rb +99 -0
- data/lib/simplecov/formatter/json_formatter.rb +87 -0
- data/lib/simplecov/formatter/multi_formatter.rb +4 -5
- data/lib/simplecov/formatter/simple_formatter.rb +9 -11
- data/lib/simplecov/formatter.rb +4 -0
- data/lib/simplecov/last_run.rb +10 -3
- data/lib/simplecov/lines_classifier.rb +25 -13
- data/lib/simplecov/load_global_config.rb +9 -4
- data/lib/simplecov/parallel_adapters/base.rb +61 -0
- data/lib/simplecov/parallel_adapters/generic.rb +44 -0
- data/lib/simplecov/parallel_adapters/parallel_tests.rb +93 -0
- data/lib/simplecov/parallel_adapters.rb +83 -0
- data/lib/simplecov/parallel_coordination.rb +129 -0
- data/lib/simplecov/process.rb +31 -13
- 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/result/missing_source_files_reporter.rb +49 -0
- data/lib/simplecov/result/source_file_builder.rb +51 -0
- data/lib/simplecov/result.rb +108 -19
- data/lib/simplecov/result_adapter.rb +70 -8
- data/lib/simplecov/result_merger/legacy_format_adapter.rb +28 -0
- data/lib/simplecov/result_merger/resultset_file.rb +38 -0
- data/lib/simplecov/result_merger/resultset_store.rb +50 -0
- data/lib/simplecov/result_merger.rb +59 -91
- data/lib/simplecov/result_processing.rb +179 -0
- data/lib/simplecov/simulate_coverage.rb +54 -8
- 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 +7 -2
- data/lib/simplecov/source_file/line_builder.rb +43 -0
- data/lib/simplecov/source_file/method.rb +52 -0
- data/lib/simplecov/source_file/method_builder.rb +58 -0
- data/lib/simplecov/source_file/ruby_data_parser.rb +88 -0
- data/lib/simplecov/source_file/skip_chunks.rb +75 -0
- data/lib/simplecov/source_file/source_loader.rb +63 -0
- data/lib/simplecov/source_file/statistics.rb +57 -0
- data/lib/simplecov/source_file.rb +66 -232
- data/lib/simplecov/static_coverage_extractor/method_collector.rb +55 -0
- data/lib/simplecov/static_coverage_extractor/visitor.rb +171 -0
- data/lib/simplecov/static_coverage_extractor.rb +110 -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 +156 -371
- data/lib/simplecov_json_formatter.rb +4 -0
- data/schemas/coverage-v1.0.schema.json +306 -0
- data/schemas/coverage.schema.json +306 -0
- metadata +90 -57
- data/CHANGELOG.md +0 -191
- data/lib/simplecov/default_formatter.rb +0 -20
data/lib/simplecov.rb
CHANGED
|
@@ -1,452 +1,231 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "English"
|
|
4
|
-
|
|
5
|
-
# Coverage may be inaccurate under JRUBY.
|
|
6
|
-
if defined?(JRUBY_VERSION) && defined?(JRuby) && !org.jruby.RubyInstanceConfig.FULL_TRACE_ENABLED
|
|
7
|
-
|
|
8
|
-
# @see https://github.com/jruby/jruby/issues/1196
|
|
9
|
-
# @see https://github.com/metricfu/metric_fu/pull/226
|
|
10
|
-
# @see https://github.com/simplecov-ruby/simplecov/issues/420
|
|
11
|
-
# @see https://github.com/simplecov-ruby/simplecov/issues/86
|
|
12
|
-
# @see https://jira.codehaus.org/browse/JRUBY-6106
|
|
13
|
-
|
|
14
|
-
warn 'Coverage may be inaccurate; set the "--debug" command line option,' \
|
|
15
|
-
' or do JRUBY_OPTS="--debug"' \
|
|
16
|
-
' or set the "debug.fullTrace=true" option in your .jrubyrc'
|
|
17
|
-
end
|
|
18
|
-
|
|
19
3
|
#
|
|
20
4
|
# Code coverage for ruby. Please check out README for a full introduction.
|
|
21
5
|
#
|
|
22
6
|
module SimpleCov
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
# Basically, should we take care of at_exit behavior or something else?
|
|
27
|
-
# Used by the minitest plugin. See lib/minitest/simplecov_plugin.rb
|
|
28
|
-
attr_accessor :external_at_exit
|
|
29
|
-
alias external_at_exit? external_at_exit
|
|
7
|
+
# Raised when a user's configuration is internally inconsistent — e.g.
|
|
8
|
+
# every coverage criterion has been disabled.
|
|
9
|
+
class ConfigurationError < StandardError; end
|
|
30
10
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
# SimpleCov.start do
|
|
39
|
-
# add_filter 'test'
|
|
40
|
-
# end
|
|
41
|
-
# OR
|
|
42
|
-
# SimpleCov.start 'rails' do
|
|
43
|
-
# add_filter 'test'
|
|
44
|
-
# end
|
|
45
|
-
#
|
|
46
|
-
# Please check out the RDoc for SimpleCov::Configuration to find about available config options
|
|
47
|
-
#
|
|
48
|
-
def start(profile = nil, &block)
|
|
49
|
-
require "coverage"
|
|
50
|
-
initial_setup(profile, &block)
|
|
51
|
-
require_relative "./simplecov/process" if SimpleCov.enabled_for_subprocesses? &&
|
|
52
|
-
::Process.respond_to?(:fork)
|
|
53
|
-
|
|
54
|
-
make_parallel_tests_available
|
|
11
|
+
class << self
|
|
12
|
+
CRITERION_TO_RUBY_COVERAGE = {
|
|
13
|
+
branch: :branches,
|
|
14
|
+
line: :lines,
|
|
15
|
+
method: :methods,
|
|
16
|
+
oneshot_line: :oneshot_lines
|
|
17
|
+
}.freeze
|
|
55
18
|
|
|
56
|
-
|
|
57
|
-
|
|
19
|
+
attr_accessor :pid
|
|
20
|
+
# When this process started tracking coverage. Captured by SimpleCov.start
|
|
21
|
+
# so JSONFormatter can detect when an existing coverage.json was written
|
|
22
|
+
# by a sibling process running concurrently.
|
|
23
|
+
attr_accessor :process_start_time
|
|
58
24
|
|
|
59
|
-
|
|
25
|
+
# A monotonically increasing serial the parent assigns to each forked
|
|
26
|
+
# subprocess (see SimpleCov::ProcessForkHook). The default `at_fork`
|
|
27
|
+
# builds the worker's command_name from this rather than the OS pid:
|
|
28
|
+
# the serial sequence is the same from one run to the next, so a re-run
|
|
29
|
+
# overwrites the previous run's resultset entries instead of writing
|
|
30
|
+
# uniquely-named ones that pile up until merge_timeout. See issue #1171.
|
|
31
|
+
def subprocess_serial
|
|
32
|
+
@subprocess_serial ||= 0
|
|
60
33
|
end
|
|
61
34
|
|
|
62
|
-
#
|
|
63
|
-
#
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
# SimpleCov.collate Dir["simplecov-resultset-*/.resultset.json"]
|
|
67
|
-
# OR
|
|
68
|
-
# SimpleCov.collate Dir["simplecov-resultset-*/.resultset.json"], 'rails' # using rails profile
|
|
69
|
-
# OR
|
|
70
|
-
# SimpleCov.collate Dir["simplecov-resultset-*/.resultset.json"] do
|
|
71
|
-
# add_filter 'test'
|
|
72
|
-
# end
|
|
73
|
-
# OR
|
|
74
|
-
# SimpleCov.collate Dir["simplecov-resultset-*/.resultset.json"], 'rails' do
|
|
75
|
-
# add_filter 'test'
|
|
76
|
-
# end
|
|
77
|
-
#
|
|
78
|
-
# Please check out the RDoc for SimpleCov::Configuration to find about
|
|
79
|
-
# available config options, or checkout the README for more in-depth
|
|
80
|
-
# information about coverage collation
|
|
81
|
-
#
|
|
82
|
-
# By default `collate` ignores the merge_timeout so all results of all files specified will be
|
|
83
|
-
# merged together. If you want to honor the merge_timeout then provide the keyword argument
|
|
84
|
-
# `ignore_timeout: false`.
|
|
85
|
-
#
|
|
86
|
-
def collate(result_filenames, profile = nil, ignore_timeout: true, &block)
|
|
87
|
-
raise "There are no reports to be merged" if result_filenames.empty?
|
|
88
|
-
|
|
89
|
-
initial_setup(profile, &block)
|
|
90
|
-
|
|
91
|
-
# Use the ResultMerger to produce a single, merged result, ready to use.
|
|
92
|
-
@result = ResultMerger.merge_and_store(*result_filenames, ignore_timeout: ignore_timeout)
|
|
93
|
-
|
|
94
|
-
run_exit_tasks!
|
|
35
|
+
# @api private — bump the serial in the parent before a fork so the
|
|
36
|
+
# child inherits its own ordinal via copy-on-write.
|
|
37
|
+
def next_subprocess_serial!
|
|
38
|
+
@subprocess_serial = subprocess_serial + 1
|
|
95
39
|
end
|
|
96
40
|
|
|
97
|
-
#
|
|
98
|
-
#
|
|
99
|
-
#
|
|
100
|
-
#
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
process_coverage_result if running
|
|
106
|
-
|
|
107
|
-
# If we're using merging of results, store the current result
|
|
108
|
-
# first (if there is one), then merge the results and return those
|
|
109
|
-
if use_merging
|
|
110
|
-
wait_for_other_processes
|
|
111
|
-
SimpleCov::ResultMerger.store_result(@result) if result?
|
|
112
|
-
@result = SimpleCov::ResultMerger.merged_result
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
@result
|
|
116
|
-
ensure
|
|
117
|
-
self.running = false
|
|
41
|
+
# @api private — true in a process that was forked while coverage was
|
|
42
|
+
# running (set by SimpleCov::ProcessForkHook in the child). Such a child
|
|
43
|
+
# stores its own slice but must not act as the final-result process: the
|
|
44
|
+
# process that forked it merges every slice and produces the report. Only
|
|
45
|
+
# consulted when no parallel-test adapter is active, since adapters answer
|
|
46
|
+
# `first_worker?` themselves. See issue #1171.
|
|
47
|
+
def forked_subprocess?
|
|
48
|
+
!!(defined?(@forked_subprocess) && @forked_subprocess)
|
|
118
49
|
end
|
|
119
50
|
|
|
120
|
-
#
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
#
|
|
124
|
-
def result?
|
|
125
|
-
defined?(@result) && @result
|
|
51
|
+
# @api private — marked in the child immediately after a fork.
|
|
52
|
+
def mark_forked_subprocess!
|
|
53
|
+
@forked_subprocess = true
|
|
126
54
|
end
|
|
55
|
+
# Should we take care of at_exit behavior or something else? Used by the
|
|
56
|
+
# minitest plugin. See lib/minitest/simplecov_plugin.rb.
|
|
57
|
+
attr_accessor :external_at_exit
|
|
127
58
|
|
|
128
|
-
#
|
|
129
|
-
#
|
|
130
|
-
#
|
|
131
|
-
def
|
|
132
|
-
|
|
133
|
-
filters.each do |filter|
|
|
134
|
-
result = result.reject { |source_file| filter.matches?(source_file) }
|
|
135
|
-
end
|
|
136
|
-
SimpleCov::FileList.new result
|
|
59
|
+
# `:oneshot_line` data is folded into the `:line` bucket of
|
|
60
|
+
# `coverage_statistics` by `ResultAdapter`, so use `:line` to look
|
|
61
|
+
# up stats for either criterion.
|
|
62
|
+
def coverage_statistics_key(criterion)
|
|
63
|
+
criterion == :oneshot_line ? :line : criterion
|
|
137
64
|
end
|
|
138
65
|
|
|
139
|
-
#
|
|
140
|
-
#
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
grouped = {}
|
|
144
|
-
grouped_files = []
|
|
145
|
-
groups.each do |name, filter|
|
|
146
|
-
grouped[name] = SimpleCov::FileList.new(files.select { |source_file| filter.matches?(source_file) })
|
|
147
|
-
grouped_files += grouped[name]
|
|
148
|
-
end
|
|
149
|
-
if !groups.empty? && !(other_files = files.reject { |source_file| grouped_files.include?(source_file) }).empty?
|
|
150
|
-
grouped["Ungrouped"] = SimpleCov::FileList.new(other_files)
|
|
151
|
-
end
|
|
152
|
-
grouped
|
|
66
|
+
# Coerce to a proper boolean so rspec-mocks 4's predicate matcher
|
|
67
|
+
# (`expect(...).not_to be_external_at_exit`) accepts the result.
|
|
68
|
+
def external_at_exit?
|
|
69
|
+
!!@external_at_exit
|
|
153
70
|
end
|
|
154
71
|
|
|
155
72
|
#
|
|
156
|
-
#
|
|
157
|
-
#
|
|
158
|
-
def load_profile(name)
|
|
159
|
-
profiles.load(name)
|
|
160
|
-
end
|
|
161
|
-
|
|
162
|
-
def load_adapter(name)
|
|
163
|
-
warn "#{Kernel.caller.first}: [DEPRECATION] #load_adapter is deprecated. Use #load_profile instead."
|
|
164
|
-
load_profile(name)
|
|
165
|
-
end
|
|
166
|
-
|
|
73
|
+
# Sets up SimpleCov to run against your project. See README for
|
|
74
|
+
# the full DSL, or:
|
|
167
75
|
#
|
|
168
|
-
#
|
|
76
|
+
# SimpleCov.start
|
|
77
|
+
# SimpleCov.start 'rails' # using a profile
|
|
78
|
+
# SimpleCov.start { add_filter 'test' } # with a config block
|
|
169
79
|
#
|
|
170
|
-
def
|
|
171
|
-
|
|
172
|
-
end
|
|
80
|
+
def start(profile = nil, &)
|
|
81
|
+
warn_about_start_in_dot_simplecov if @autoloading_dot_simplecov
|
|
173
82
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
# If SimpleCov is no longer running then don't run exit tasks
|
|
179
|
-
SimpleCov.run_exit_tasks! if SimpleCov.running
|
|
83
|
+
initial_setup(profile, &)
|
|
84
|
+
start_tracking
|
|
85
|
+
install_at_exit_hook
|
|
180
86
|
end
|
|
181
87
|
|
|
182
88
|
# @api private
|
|
183
89
|
#
|
|
184
|
-
#
|
|
185
|
-
#
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
90
|
+
# Mark the duration of a `.simplecov` auto-load so any `SimpleCov.start`
|
|
91
|
+
# call inside the file can warn about the impending migration to a
|
|
92
|
+
# config-only file. Tracking still begins for backward compatibility;
|
|
93
|
+
# the warning is the cue to move `SimpleCov.start` into a test helper.
|
|
94
|
+
# See #581.
|
|
95
|
+
def with_dot_simplecov_autoload
|
|
96
|
+
previous = @autoloading_dot_simplecov
|
|
97
|
+
@autoloading_dot_simplecov = true
|
|
98
|
+
yield
|
|
99
|
+
ensure
|
|
100
|
+
@autoloading_dot_simplecov = previous
|
|
193
101
|
end
|
|
194
102
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
#
|
|
198
|
-
# Returns the exit status from the exit exception
|
|
199
|
-
#
|
|
200
|
-
def exit_status_from_exception
|
|
201
|
-
# Capture the current exception if it exists
|
|
202
|
-
@exit_exception = $ERROR_INFO
|
|
203
|
-
return nil unless @exit_exception
|
|
204
|
-
|
|
205
|
-
if @exit_exception.is_a?(SystemExit)
|
|
206
|
-
@exit_exception.status
|
|
207
|
-
else
|
|
208
|
-
SimpleCov::ExitCodes::EXCEPTION
|
|
209
|
-
end
|
|
210
|
-
end
|
|
103
|
+
def warn_about_start_in_dot_simplecov
|
|
104
|
+
return if @dot_simplecov_start_warned
|
|
211
105
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
106
|
+
@dot_simplecov_start_warned = true
|
|
107
|
+
warn "[DEPRECATION] Calling `SimpleCov.start` from `.simplecov` is deprecated and will " \
|
|
108
|
+
"be removed in a future release. `.simplecov` should contain configuration only; " \
|
|
109
|
+
"move the `SimpleCov.start` call into your `spec_helper.rb` / `test_helper.rb`. " \
|
|
110
|
+
"Coverage tracking still begins for backward compatibility, but a future release " \
|
|
111
|
+
"will require the explicit `SimpleCov.start` from a test helper. " \
|
|
112
|
+
"See https://github.com/simplecov-ruby/simplecov/issues/581."
|
|
217
113
|
end
|
|
218
114
|
|
|
219
115
|
#
|
|
220
|
-
#
|
|
116
|
+
# Install the at_exit hook that formats results and runs exit-code
|
|
117
|
+
# checks. `SimpleCov.start` calls this automatically. Idempotent —
|
|
118
|
+
# safe to call multiple times. Callers that drive the formatting
|
|
119
|
+
# pipeline themselves (e.g., dogfood test setups) can skip it by
|
|
120
|
+
# using `start_tracking` directly instead of `start`.
|
|
221
121
|
#
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
warn("Stopped processing SimpleCov as a previous error not related to SimpleCov has been detected") if print_error_status
|
|
225
|
-
Kernel.exit(exit_status)
|
|
226
|
-
end
|
|
227
|
-
|
|
228
|
-
# @api private
|
|
229
|
-
def ready_to_process_results?
|
|
230
|
-
final_result_process? && result?
|
|
231
|
-
end
|
|
122
|
+
def install_at_exit_hook
|
|
123
|
+
return if @at_exit_hook_installed
|
|
232
124
|
|
|
233
|
-
|
|
234
|
-
|
|
125
|
+
@at_exit_hook_installed = true
|
|
126
|
+
defer_to_minitest_after_run if minitest_autorun_pending?
|
|
127
|
+
Kernel.at_exit do
|
|
128
|
+
next if SimpleCov.external_at_exit?
|
|
235
129
|
|
|
236
|
-
|
|
237
|
-
if exit_status.positive?
|
|
238
|
-
warn("SimpleCov failed with exit #{exit_status} due to a coverage related error") if print_error_status
|
|
239
|
-
Kernel.exit exit_status
|
|
130
|
+
SimpleCov.at_exit_behavior
|
|
240
131
|
end
|
|
241
132
|
end
|
|
242
133
|
|
|
243
|
-
# @api private
|
|
244
|
-
#
|
|
245
|
-
# Usage:
|
|
246
|
-
# exit_status = SimpleCov.process_result(SimpleCov.result, exit_status)
|
|
247
|
-
#
|
|
248
|
-
def process_result(result)
|
|
249
|
-
result_exit_status = result_exit_status(result)
|
|
250
|
-
write_last_run(result) if result_exit_status == SimpleCov::ExitCodes::SUCCESS
|
|
251
|
-
result_exit_status
|
|
252
|
-
end
|
|
253
|
-
|
|
254
|
-
# @api private
|
|
255
|
-
CoverageLimits = Struct.new(:minimum_coverage, :minimum_coverage_by_file, :maximum_coverage_drop, keyword_init: true)
|
|
256
|
-
def result_exit_status(result)
|
|
257
|
-
coverage_limits = CoverageLimits.new(
|
|
258
|
-
minimum_coverage: minimum_coverage, minimum_coverage_by_file: minimum_coverage_by_file,
|
|
259
|
-
maximum_coverage_drop: maximum_coverage_drop
|
|
260
|
-
)
|
|
261
|
-
|
|
262
|
-
ExitCodes::ExitCodeHandling.call(result, coverage_limits: coverage_limits)
|
|
263
|
-
end
|
|
264
|
-
|
|
265
|
-
#
|
|
266
|
-
# @api private
|
|
267
|
-
#
|
|
268
|
-
def final_result_process?
|
|
269
|
-
# checking for ENV["TEST_ENV_NUMBER"] to determine if the tests are being run in parallel
|
|
270
|
-
!defined?(ParallelTests) || !ENV["TEST_ENV_NUMBER"] || ParallelTests.last_process?
|
|
271
|
-
end
|
|
272
|
-
|
|
273
134
|
#
|
|
274
|
-
#
|
|
135
|
+
# Begin coverage tracking without applying configuration. Pairs with
|
|
136
|
+
# `SimpleCov.configure { ... }` for callers that want to separate
|
|
137
|
+
# the two — for example a dogfood test that has already started
|
|
138
|
+
# `Coverage` itself before requiring simplecov, but still wants the
|
|
139
|
+
# process_start_time / pid / fork-hook bookkeeping.
|
|
275
140
|
#
|
|
276
|
-
def
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
141
|
+
def start_tracking
|
|
142
|
+
require "coverage"
|
|
143
|
+
warn_if_jruby_full_trace_disabled
|
|
144
|
+
validate_coverage_criteria!
|
|
145
|
+
# simplecov:disable — fork-hook is enabled via SimpleCov.enable_for_subprocesses, off by default
|
|
146
|
+
require_relative "simplecov/process" if SimpleCov.enabled_for_subprocesses? &&
|
|
147
|
+
::Process.respond_to?(:_fork)
|
|
148
|
+
# simplecov:enable
|
|
149
|
+
|
|
150
|
+
# Trigger adapter selection now so the (possibly lazy) parallel_tests
|
|
151
|
+
# gem load happens at start_tracking time rather than mid-suite.
|
|
152
|
+
# `current` is memoized; subsequent calls are cheap.
|
|
153
|
+
SimpleCov::ParallelAdapters.current
|
|
281
154
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
def write_last_run(result)
|
|
286
|
-
SimpleCov::LastRun.write(result:
|
|
287
|
-
result.coverage_statistics.transform_values do |stats|
|
|
288
|
-
round_coverage(stats.percent)
|
|
289
|
-
end)
|
|
290
|
-
end
|
|
155
|
+
@result = nil
|
|
156
|
+
self.pid = Process.pid
|
|
157
|
+
self.process_start_time = Time.now
|
|
291
158
|
|
|
292
|
-
|
|
293
|
-
# @api private
|
|
294
|
-
#
|
|
295
|
-
# Rounding down to be extra strict, see #679
|
|
296
|
-
def round_coverage(coverage)
|
|
297
|
-
coverage.floor(2)
|
|
159
|
+
start_coverage_measurement
|
|
298
160
|
end
|
|
299
161
|
|
|
300
162
|
private
|
|
301
163
|
|
|
302
|
-
def initial_setup(profile, &block)
|
|
303
|
-
load_profile(profile) if profile
|
|
304
|
-
configure(&block) if block_given?
|
|
305
|
-
self.running = true
|
|
306
|
-
end
|
|
307
|
-
|
|
308
|
-
#
|
|
309
|
-
# Trigger Coverage.start depends on given config coverage_criterion
|
|
310
164
|
#
|
|
311
|
-
#
|
|
312
|
-
#
|
|
165
|
+
# Trigger Coverage.start with the configured criteria. Every supported
|
|
166
|
+
# runtime (CRuby >= 3.2, JRuby >= 10, TruffleRuby >= 22) accepts the
|
|
167
|
+
# criteria-hash form, so no compatibility fallback is needed.
|
|
313
168
|
#
|
|
314
169
|
def start_coverage_measurement
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
# There is also a nice writeup of the different coverage criteria made in this
|
|
318
|
-
# comment https://github.com/simplecov-ruby/simplecov/pull/692#discussion_r281836176 :
|
|
319
|
-
# Ruby < 2.5:
|
|
320
|
-
# https://github.com/ruby/ruby/blob/v1_9_3_374/ext/coverage/coverage.c
|
|
321
|
-
# traditional mode (Array)
|
|
322
|
-
#
|
|
323
|
-
# Ruby 2.5:
|
|
324
|
-
# https://bugs.ruby-lang.org/issues/13901
|
|
325
|
-
# https://github.com/ruby/ruby/blob/v2_5_3/ext/coverage/coverage.c
|
|
326
|
-
# default: traditional/compatible mode (Array)
|
|
327
|
-
# :lines - like traditional mode but using Hash
|
|
328
|
-
# :branches
|
|
329
|
-
# :methods
|
|
330
|
-
# :all - same as lines + branches + methods
|
|
331
|
-
#
|
|
332
|
-
# Ruby >= 2.6:
|
|
333
|
-
# https://bugs.ruby-lang.org/issues/15022
|
|
334
|
-
# https://github.com/ruby/ruby/blob/v2_6_3/ext/coverage/coverage.c
|
|
335
|
-
# default: traditional/compatible mode (Array)
|
|
336
|
-
# :lines - like traditional mode but using Hash
|
|
337
|
-
# :branches
|
|
338
|
-
# :methods
|
|
339
|
-
# :oneshot_lines - can not be combined with lines
|
|
340
|
-
# :all - same as lines + branches + methods
|
|
341
|
-
#
|
|
342
|
-
if coverage_start_arguments_supported?
|
|
343
|
-
start_coverage_with_criteria
|
|
344
|
-
else
|
|
345
|
-
Coverage.start unless Coverage.running?
|
|
170
|
+
start_arguments = coverage_criteria.to_h do |criterion|
|
|
171
|
+
[CRITERION_TO_RUBY_COVERAGE.fetch(criterion), true]
|
|
346
172
|
end
|
|
347
|
-
end
|
|
348
|
-
|
|
349
|
-
def start_coverage_with_criteria
|
|
350
|
-
start_arguments = coverage_criteria.map do |criterion|
|
|
351
|
-
[lookup_corresponding_ruby_coverage_name(criterion), true]
|
|
352
|
-
end.to_h
|
|
353
173
|
|
|
354
174
|
start_arguments[:eval] = true if coverage_for_eval_enabled?
|
|
355
175
|
|
|
356
176
|
Coverage.start(start_arguments) unless Coverage.running?
|
|
357
177
|
end
|
|
358
178
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
# the line-by-line coverage to zero (if relevant) or nil (comments / whitespace etc).
|
|
370
|
-
#
|
|
371
|
-
def add_not_loaded_files(result)
|
|
372
|
-
if tracked_files
|
|
373
|
-
result = result.dup
|
|
374
|
-
Dir[tracked_files].each do |file|
|
|
375
|
-
absolute_path = File.expand_path(file)
|
|
376
|
-
result[absolute_path] ||= SimulateCoverage.call(absolute_path)
|
|
377
|
-
end
|
|
378
|
-
end
|
|
179
|
+
# `Rake::TestTask` runs `ruby -e 'require "minitest/autorun"; ...'`,
|
|
180
|
+
# which means Minitest's at_exit registers before SimpleCov's. Since
|
|
181
|
+
# at_exit fires LIFO, SimpleCov's hook would otherwise run *before*
|
|
182
|
+
# Minitest gets a chance to invoke the tests — and format an empty
|
|
183
|
+
# resultset. When we can see that Minitest is loaded and its autorun
|
|
184
|
+
# is armed, route the report through `Minitest.after_run` instead,
|
|
185
|
+
# which fires after the suite completes. See issues #1099 and #1112.
|
|
186
|
+
def minitest_autorun_pending?
|
|
187
|
+
return false unless defined?(Minitest) && Minitest.respond_to?(:after_run)
|
|
188
|
+
return false unless Minitest.class_variable_defined?(:@@installed_at_exit)
|
|
379
189
|
|
|
380
|
-
|
|
190
|
+
Minitest.class_variable_get(:@@installed_at_exit)
|
|
381
191
|
end
|
|
382
192
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
# @return [Hash]
|
|
387
|
-
#
|
|
388
|
-
def process_coverage_result
|
|
389
|
-
adapt_coverage_result
|
|
390
|
-
remove_useless_results
|
|
391
|
-
result_with_not_loaded_files
|
|
193
|
+
def defer_to_minitest_after_run
|
|
194
|
+
self.external_at_exit = true
|
|
195
|
+
Minitest.after_run { SimpleCov.at_exit_behavior }
|
|
392
196
|
end
|
|
393
197
|
|
|
394
|
-
#
|
|
395
|
-
#
|
|
396
|
-
#
|
|
397
|
-
# @
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
@result = SimpleCov::ResultAdapter.call(Coverage.result)
|
|
401
|
-
end
|
|
402
|
-
|
|
403
|
-
#
|
|
404
|
-
# Filter coverage result
|
|
405
|
-
# The result before filter also has result of coverage for files
|
|
406
|
-
# are not related to the project like loaded gems coverage.
|
|
407
|
-
#
|
|
408
|
-
# @return [Hash]
|
|
409
|
-
#
|
|
410
|
-
def remove_useless_results
|
|
411
|
-
@result = SimpleCov::UselessResultsRemover.call(@result)
|
|
412
|
-
end
|
|
198
|
+
# JRuby coverage data is unreliable unless full-trace mode is enabled.
|
|
199
|
+
# @see https://github.com/jruby/jruby/issues/1196
|
|
200
|
+
# @see https://github.com/simplecov-ruby/simplecov/issues/420
|
|
201
|
+
# @see https://github.com/simplecov-ruby/simplecov/issues/86
|
|
202
|
+
def warn_if_jruby_full_trace_disabled
|
|
203
|
+
return unless defined?(JRUBY_VERSION) && defined?(JRuby) # simplecov:disable — JRuby-only branch
|
|
413
204
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
# and added inside the config block
|
|
417
|
-
#
|
|
418
|
-
# @return [Hash]
|
|
419
|
-
#
|
|
420
|
-
def result_with_not_loaded_files
|
|
421
|
-
@result = SimpleCov::Result.new(add_not_loaded_files(@result))
|
|
422
|
-
end
|
|
423
|
-
|
|
424
|
-
# parallel_tests isn't always available, see: https://github.com/grosser/parallel_tests/issues/772
|
|
425
|
-
def make_parallel_tests_available
|
|
426
|
-
return if defined?(ParallelTests)
|
|
427
|
-
return unless probably_running_parallel_tests?
|
|
428
|
-
|
|
429
|
-
require "parallel_tests"
|
|
430
|
-
rescue LoadError
|
|
431
|
-
warn("SimpleCov guessed you were running inside parallel tests but couldn't load it. Please file a bug report with us!")
|
|
432
|
-
end
|
|
205
|
+
# simplecov:disable — JRuby-only branches; unreachable from CRuby
|
|
206
|
+
return if org.jruby.RubyInstanceConfig.FULL_TRACE_ENABLED
|
|
433
207
|
|
|
434
|
-
|
|
435
|
-
|
|
208
|
+
warn 'Coverage may be inaccurate; set the "--debug" command line option, ' \
|
|
209
|
+
'or do JRUBY_OPTS="--debug" ' \
|
|
210
|
+
'or set the "debug.fullTrace=true" option in your .jrubyrc'
|
|
211
|
+
# simplecov:enable
|
|
436
212
|
end
|
|
437
213
|
end
|
|
438
214
|
end
|
|
439
215
|
|
|
440
|
-
# requires are down here
|
|
441
|
-
require "set"
|
|
216
|
+
# requires are down here for a load order reason I'm not sure what it is about
|
|
442
217
|
require "forwardable"
|
|
218
|
+
require_relative "simplecov/color"
|
|
219
|
+
require_relative "simplecov/deprecation"
|
|
443
220
|
require_relative "simplecov/configuration"
|
|
444
221
|
SimpleCov.extend SimpleCov::Configuration
|
|
445
222
|
require_relative "simplecov/coverage_statistics"
|
|
223
|
+
require_relative "simplecov/coverage_violations"
|
|
446
224
|
require_relative "simplecov/exit_codes"
|
|
447
225
|
require_relative "simplecov/profiles"
|
|
448
226
|
require_relative "simplecov/source_file/line"
|
|
449
227
|
require_relative "simplecov/source_file/branch"
|
|
228
|
+
require_relative "simplecov/source_file/method"
|
|
450
229
|
require_relative "simplecov/source_file"
|
|
451
230
|
require_relative "simplecov/file_list"
|
|
452
231
|
require_relative "simplecov/result"
|
|
@@ -455,16 +234,22 @@ require_relative "simplecov/formatter"
|
|
|
455
234
|
require_relative "simplecov/last_run"
|
|
456
235
|
require_relative "simplecov/lines_classifier"
|
|
457
236
|
require_relative "simplecov/result_merger"
|
|
237
|
+
require_relative "simplecov/parallel_adapters"
|
|
458
238
|
require_relative "simplecov/command_guesser"
|
|
459
239
|
require_relative "simplecov/version"
|
|
460
240
|
require_relative "simplecov/result_adapter"
|
|
461
241
|
require_relative "simplecov/combine"
|
|
462
242
|
require_relative "simplecov/combine/branches_combiner"
|
|
243
|
+
require_relative "simplecov/combine/methods_combiner"
|
|
463
244
|
require_relative "simplecov/combine/files_combiner"
|
|
464
245
|
require_relative "simplecov/combine/lines_combiner"
|
|
465
246
|
require_relative "simplecov/combine/results_combiner"
|
|
466
247
|
require_relative "simplecov/useless_results_remover"
|
|
467
248
|
require_relative "simplecov/simulate_coverage"
|
|
249
|
+
require_relative "simplecov/result_processing"
|
|
250
|
+
require_relative "simplecov/exit_handling"
|
|
251
|
+
require_relative "simplecov/parallel_coordination"
|
|
468
252
|
|
|
469
253
|
# Load default config
|
|
254
|
+
# simplecov:disable — env-var only set by aruba feature tests
|
|
470
255
|
require_relative "simplecov/defaults" unless ENV["SIMPLECOV_NO_DEFAULTS"]
|