simplecov 0.22.0 → 1.0.2
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 +93 -0
- data/lib/simplecov/cli/diff.rb +152 -0
- data/lib/simplecov/cli/dotfile.rb +105 -0
- data/lib/simplecov/cli/merge.rb +118 -0
- data/lib/simplecov/cli/open.rb +50 -0
- data/lib/simplecov/cli/report.rb +89 -0
- data/lib/simplecov/cli/run.rb +36 -0
- data/lib/simplecov/cli/serve.rb +149 -0
- data/lib/simplecov/cli/uncovered.rb +108 -0
- data/lib/simplecov/cli.rb +150 -0
- data/lib/simplecov/color.rb +79 -0
- data/lib/simplecov/combine/branches_combiner.rb +28 -5
- data/lib/simplecov/combine/files_combiner.rb +47 -1
- data/lib/simplecov/combine/lines_combiner.rb +19 -17
- data/lib/simplecov/combine/methods_combiner.rb +49 -0
- data/lib/simplecov/combine/results_combiner.rb +7 -5
- data/lib/simplecov/command_guesser.rb +46 -32
- data/lib/simplecov/configuration/coverage.rb +175 -0
- data/lib/simplecov/configuration/coverage_criteria.rb +158 -0
- data/lib/simplecov/configuration/filters.rb +197 -0
- data/lib/simplecov/configuration/formatting.rb +129 -0
- data/lib/simplecov/configuration/ignored_entries.rb +63 -0
- data/lib/simplecov/configuration/merging.rb +164 -0
- data/lib/simplecov/configuration/thresholds.rb +178 -0
- data/lib/simplecov/configuration.rb +105 -412
- data/lib/simplecov/coverage_statistics.rb +15 -9
- data/lib/simplecov/coverage_violations.rb +149 -0
- data/lib/simplecov/defaults.rb +29 -22
- data/lib/simplecov/deprecation.rb +45 -0
- data/lib/simplecov/directive.rb +167 -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 +15 -0
- data/lib/simplecov/exit_handling.rb +158 -0
- data/lib/simplecov/file_list.rb +70 -19
- data/lib/simplecov/filter.rb +69 -24
- data/lib/simplecov/formatter/base.rb +102 -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 +85 -0
- data/lib/simplecov/formatter/json_formatter/errors_formatter.rb +90 -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 +89 -0
- data/lib/simplecov/formatter/multi_formatter.rb +11 -7
- data/lib/simplecov/formatter/simple_formatter.rb +11 -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 +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/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 +105 -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 +9 -4
- 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 +60 -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/condition_folding.rb +49 -0
- data/lib/simplecov/static_coverage_extractor/location_conventions.rb +247 -0
- data/lib/simplecov/static_coverage_extractor/method_collector.rb +55 -0
- data/lib/simplecov/static_coverage_extractor/value_position.rb +82 -0
- data/lib/simplecov/static_coverage_extractor/visitor.rb +196 -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 +178 -380
- data/lib/simplecov_json_formatter.rb +4 -0
- data/schemas/coverage-v1.0.schema.json +306 -0
- data/schemas/coverage.schema.json +306 -0
- data/sig/simplecov.rbs +1638 -0
- metadata +94 -57
- data/CHANGELOG.md +0 -191
- data/lib/simplecov/default_formatter.rb +0 -20
data/lib/simplecov.rb
CHANGED
|
@@ -1,452 +1,244 @@
|
|
|
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
|
-
|
|
7
|
+
# Raised when a user's configuration is internally inconsistent — e.g.
|
|
8
|
+
# every coverage criterion has been disabled.
|
|
9
|
+
class ConfigurationError < StandardError; end
|
|
10
|
+
|
|
11
|
+
# Maps SimpleCov's criterion names to the keys `Coverage.start` expects.
|
|
12
|
+
# Lives at module scope (not inside `class << self`) so it can be
|
|
13
|
+
# declared in the RBS signatures; lexical scoping keeps every existing
|
|
14
|
+
# reference inside the singleton class working.
|
|
15
|
+
CRITERION_TO_RUBY_COVERAGE = {
|
|
16
|
+
branch: :branches,
|
|
17
|
+
line: :lines,
|
|
18
|
+
method: :methods,
|
|
19
|
+
oneshot_line: :oneshot_lines
|
|
20
|
+
}.freeze
|
|
25
21
|
|
|
26
|
-
|
|
27
|
-
|
|
22
|
+
class << self
|
|
23
|
+
attr_accessor :pid
|
|
24
|
+
# When this process started tracking coverage. Captured by SimpleCov.start
|
|
25
|
+
# so JSONFormatter can detect when an existing coverage.json was written
|
|
26
|
+
# by a sibling process running concurrently.
|
|
27
|
+
attr_accessor :process_start_time
|
|
28
|
+
|
|
29
|
+
# A monotonically increasing serial the parent assigns to each forked
|
|
30
|
+
# subprocess (see SimpleCov::ProcessForkHook). The default `at_fork`
|
|
31
|
+
# builds the worker's command_name from this rather than the OS pid:
|
|
32
|
+
# the serial sequence is the same from one run to the next, so a re-run
|
|
33
|
+
# overwrites the previous run's resultset entries instead of writing
|
|
34
|
+
# uniquely-named ones that pile up until merge_timeout. See issue #1171.
|
|
35
|
+
def subprocess_serial
|
|
36
|
+
@subprocess_serial ||= 0
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# @api private — bump the serial in the parent before a fork so the
|
|
40
|
+
# child inherits its own ordinal via copy-on-write.
|
|
41
|
+
def next_subprocess_serial!
|
|
42
|
+
@subprocess_serial = subprocess_serial + 1
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# @api private — true in a process that was forked while coverage was
|
|
46
|
+
# running (set by SimpleCov::ProcessForkHook in the child). Such a child
|
|
47
|
+
# stores its own slice but must not act as the final-result process: the
|
|
48
|
+
# process that forked it merges every slice and produces the report. Only
|
|
49
|
+
# consulted when no parallel-test adapter is active, since adapters answer
|
|
50
|
+
# `first_worker?` themselves. See issue #1171.
|
|
51
|
+
def forked_subprocess?
|
|
52
|
+
!!(defined?(@forked_subprocess) && @forked_subprocess)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# @api private — marked in the child immediately after a fork.
|
|
56
|
+
def mark_forked_subprocess!
|
|
57
|
+
@forked_subprocess = true
|
|
58
|
+
end
|
|
59
|
+
# Should we take care of at_exit behavior or something else? Used by the
|
|
60
|
+
# minitest plugin. See lib/minitest/simplecov_plugin.rb.
|
|
28
61
|
attr_accessor :external_at_exit
|
|
29
|
-
alias external_at_exit? external_at_exit
|
|
30
|
-
|
|
31
|
-
#
|
|
32
|
-
# Sets up SimpleCov to run against your project.
|
|
33
|
-
# You can optionally specify a profile to use as well as configuration with a block:
|
|
34
|
-
# SimpleCov.start
|
|
35
|
-
# OR
|
|
36
|
-
# SimpleCov.start 'rails' # using rails profile
|
|
37
|
-
# OR
|
|
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
|
|
55
|
-
|
|
56
|
-
@result = nil
|
|
57
|
-
self.pid = Process.pid
|
|
58
|
-
|
|
59
|
-
start_coverage_measurement
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
#
|
|
63
|
-
# Collate a series of SimpleCov result files into a single SimpleCov output.
|
|
64
|
-
#
|
|
65
|
-
# You can optionally specify configuration with a block:
|
|
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!
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
#
|
|
98
|
-
# Returns the result for the current coverage run, merging it across test suites
|
|
99
|
-
# from cache using SimpleCov::ResultMerger if use_merging is activated (default)
|
|
100
|
-
#
|
|
101
|
-
def result
|
|
102
|
-
return @result if result?
|
|
103
|
-
|
|
104
|
-
# Collect our coverage result
|
|
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
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
#
|
|
121
|
-
# Returns nil if the result has not been computed
|
|
122
|
-
# Otherwise, returns the result
|
|
123
|
-
#
|
|
124
|
-
def result?
|
|
125
|
-
defined?(@result) && @result
|
|
126
|
-
end
|
|
127
62
|
|
|
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
|
|
63
|
+
# `:oneshot_line` data is folded into the `:line` bucket of
|
|
64
|
+
# `coverage_statistics` by `ResultAdapter`, so use `:line` to look
|
|
65
|
+
# up stats for either criterion.
|
|
66
|
+
def coverage_statistics_key(criterion)
|
|
67
|
+
criterion == :oneshot_line ? :line : criterion
|
|
137
68
|
end
|
|
138
69
|
|
|
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
|
|
70
|
+
# Coerce to a proper boolean so rspec-mocks 4's predicate matcher
|
|
71
|
+
# (`expect(...).not_to be_external_at_exit`) accepts the result.
|
|
72
|
+
def external_at_exit?
|
|
73
|
+
!!@external_at_exit
|
|
153
74
|
end
|
|
154
75
|
|
|
155
76
|
#
|
|
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
|
-
|
|
77
|
+
# Sets up SimpleCov to run against your project. See README for
|
|
78
|
+
# the full DSL, or:
|
|
167
79
|
#
|
|
168
|
-
#
|
|
80
|
+
# SimpleCov.start
|
|
81
|
+
# SimpleCov.start 'rails' # using a profile
|
|
82
|
+
# SimpleCov.start { add_filter 'test' } # with a config block
|
|
169
83
|
#
|
|
170
|
-
def
|
|
171
|
-
|
|
172
|
-
end
|
|
84
|
+
def start(profile = nil, &)
|
|
85
|
+
warn_about_start_in_dot_simplecov if @autoloading_dot_simplecov
|
|
173
86
|
|
|
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
|
|
87
|
+
initial_setup(profile, &)
|
|
88
|
+
start_tracking
|
|
89
|
+
install_at_exit_hook
|
|
180
90
|
end
|
|
181
91
|
|
|
182
92
|
# @api private
|
|
183
93
|
#
|
|
184
|
-
#
|
|
185
|
-
#
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
94
|
+
# Mark the duration of a `.simplecov` auto-load so any `SimpleCov.start`
|
|
95
|
+
# call inside the file can warn about the impending migration to a
|
|
96
|
+
# config-only file. Tracking still begins for backward compatibility;
|
|
97
|
+
# the warning is the cue to move `SimpleCov.start` into a test helper.
|
|
98
|
+
# See #581.
|
|
99
|
+
def with_dot_simplecov_autoload
|
|
100
|
+
# Read in the ensure clause, where flow analysis cannot see the
|
|
101
|
+
# assignment above; anchor the type here.
|
|
102
|
+
previous = @autoloading_dot_simplecov # : bool?
|
|
103
|
+
@autoloading_dot_simplecov = true
|
|
104
|
+
yield
|
|
105
|
+
ensure
|
|
106
|
+
# @type var previous: bool?
|
|
107
|
+
@autoloading_dot_simplecov = previous
|
|
193
108
|
end
|
|
194
109
|
|
|
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
|
|
110
|
+
def warn_about_start_in_dot_simplecov
|
|
111
|
+
return if @dot_simplecov_start_warned
|
|
211
112
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
113
|
+
@dot_simplecov_start_warned = true
|
|
114
|
+
warn "[DEPRECATION] Calling `SimpleCov.start` from `.simplecov` is deprecated and will " \
|
|
115
|
+
"be removed in a future release. `.simplecov` should contain configuration only; " \
|
|
116
|
+
"move the `SimpleCov.start` call into your `spec_helper.rb` / `test_helper.rb`. " \
|
|
117
|
+
"Coverage tracking still begins for backward compatibility, but a future release " \
|
|
118
|
+
"will require the explicit `SimpleCov.start` from a test helper. " \
|
|
119
|
+
"See https://github.com/simplecov-ruby/simplecov/issues/581."
|
|
217
120
|
end
|
|
218
121
|
|
|
219
122
|
#
|
|
220
|
-
#
|
|
123
|
+
# Install the at_exit hook that formats results and runs exit-code
|
|
124
|
+
# checks. `SimpleCov.start` calls this automatically. Idempotent —
|
|
125
|
+
# safe to call multiple times. Callers that drive the formatting
|
|
126
|
+
# pipeline themselves (e.g., dogfood test setups) can skip it by
|
|
127
|
+
# using `start_tracking` directly instead of `start`.
|
|
221
128
|
#
|
|
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
|
|
129
|
+
def install_at_exit_hook
|
|
130
|
+
return if @at_exit_hook_installed
|
|
227
131
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
132
|
+
@at_exit_hook_installed = true
|
|
133
|
+
# Never defer in a forked child: Minitest pins its after_run at_exit
|
|
134
|
+
# to the pid that armed autorun, so the deferral target can't fire
|
|
135
|
+
# there and the child's resultset would be silently dropped. See
|
|
136
|
+
# issue #1227.
|
|
137
|
+
defer_to_minitest_after_run if minitest_autorun_pending? && !forked_subprocess?
|
|
138
|
+
Kernel.at_exit do
|
|
139
|
+
next if SimpleCov.external_at_exit?
|
|
232
140
|
|
|
233
|
-
|
|
234
|
-
exit_status = process_result(result)
|
|
235
|
-
|
|
236
|
-
# Force exit with stored status (see github issue #5)
|
|
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
|
|
141
|
+
SimpleCov.at_exit_behavior
|
|
240
142
|
end
|
|
241
143
|
end
|
|
242
144
|
|
|
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
145
|
#
|
|
274
|
-
#
|
|
146
|
+
# Begin coverage tracking without applying configuration. Pairs with
|
|
147
|
+
# `SimpleCov.configure { ... }` for callers that want to separate
|
|
148
|
+
# the two — for example a dogfood test that has already started
|
|
149
|
+
# `Coverage` itself before requiring simplecov, but still wants the
|
|
150
|
+
# process_start_time / pid / fork-hook bookkeeping.
|
|
275
151
|
#
|
|
276
|
-
def
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
152
|
+
def start_tracking
|
|
153
|
+
require "coverage"
|
|
154
|
+
warn_if_jruby_full_trace_disabled
|
|
155
|
+
validate_coverage_criteria!
|
|
156
|
+
# simplecov:disable — fork-hook is enabled via SimpleCov.enable_for_subprocesses, off by default
|
|
157
|
+
require_relative "simplecov/process" if SimpleCov.enabled_for_subprocesses? &&
|
|
158
|
+
::Process.respond_to?(:_fork)
|
|
159
|
+
# simplecov:enable
|
|
160
|
+
|
|
161
|
+
# Trigger adapter selection now so the (possibly lazy) parallel_tests
|
|
162
|
+
# gem load happens at start_tracking time rather than mid-suite.
|
|
163
|
+
# `current` is memoized; subsequent calls are cheap.
|
|
164
|
+
SimpleCov::ParallelAdapters.current
|
|
281
165
|
|
|
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
|
|
166
|
+
@result = nil
|
|
167
|
+
self.pid = Process.pid
|
|
168
|
+
self.process_start_time = Time.now
|
|
291
169
|
|
|
292
|
-
|
|
293
|
-
# @api private
|
|
294
|
-
#
|
|
295
|
-
# Rounding down to be extra strict, see #679
|
|
296
|
-
def round_coverage(coverage)
|
|
297
|
-
coverage.floor(2)
|
|
170
|
+
start_coverage_measurement
|
|
298
171
|
end
|
|
299
172
|
|
|
300
173
|
private
|
|
301
174
|
|
|
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
175
|
#
|
|
309
|
-
# Trigger Coverage.start
|
|
310
|
-
#
|
|
311
|
-
#
|
|
312
|
-
# With Negative branch it supports only line coverage measurement type
|
|
176
|
+
# Trigger Coverage.start with the configured criteria. Every supported
|
|
177
|
+
# runtime (CRuby >= 3.2, JRuby >= 10, TruffleRuby >= 22) accepts the
|
|
178
|
+
# criteria-hash form, so no compatibility fallback is needed.
|
|
313
179
|
#
|
|
314
180
|
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?
|
|
181
|
+
start_arguments = coverage_criteria.to_h do |criterion|
|
|
182
|
+
[CRITERION_TO_RUBY_COVERAGE.fetch(criterion), true]
|
|
346
183
|
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
184
|
|
|
354
185
|
start_arguments[:eval] = true if coverage_for_eval_enabled?
|
|
355
186
|
|
|
356
|
-
Coverage.start(start_arguments) unless Coverage.running?
|
|
357
|
-
end
|
|
358
|
-
|
|
359
|
-
CRITERION_TO_RUBY_COVERAGE = {
|
|
360
|
-
branch: :branches,
|
|
361
|
-
line: :lines
|
|
362
|
-
}.freeze
|
|
363
|
-
def lookup_corresponding_ruby_coverage_name(criterion)
|
|
364
|
-
CRITERION_TO_RUBY_COVERAGE.fetch(criterion)
|
|
187
|
+
Coverage.start(**start_arguments) unless Coverage.running?
|
|
365
188
|
end
|
|
366
189
|
|
|
367
|
-
#
|
|
368
|
-
#
|
|
369
|
-
#
|
|
370
|
-
#
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
end
|
|
378
|
-
end
|
|
190
|
+
# `Rake::TestTask` runs `ruby -e 'require "minitest/autorun"; ...'`,
|
|
191
|
+
# which means Minitest's at_exit registers before SimpleCov's. Since
|
|
192
|
+
# at_exit fires LIFO, SimpleCov's hook would otherwise run *before*
|
|
193
|
+
# Minitest gets a chance to invoke the tests — and format an empty
|
|
194
|
+
# resultset. When we can see that Minitest is loaded and its autorun
|
|
195
|
+
# is armed, route the report through `Minitest.after_run` instead,
|
|
196
|
+
# which fires after the suite completes. See issues #1099 and #1112.
|
|
197
|
+
def minitest_autorun_pending?
|
|
198
|
+
return false unless defined?(Minitest) && Minitest.respond_to?(:after_run)
|
|
199
|
+
return false unless Minitest.class_variable_defined?(:@@installed_at_exit)
|
|
379
200
|
|
|
380
|
-
|
|
201
|
+
Minitest.class_variable_get(:@@installed_at_exit)
|
|
381
202
|
end
|
|
382
203
|
|
|
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
|
|
204
|
+
def defer_to_minitest_after_run
|
|
205
|
+
self.external_at_exit = true
|
|
206
|
+
Minitest.after_run { SimpleCov.at_exit_behavior }
|
|
392
207
|
end
|
|
393
208
|
|
|
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
|
|
209
|
+
# JRuby coverage data is unreliable unless full-trace mode is enabled.
|
|
210
|
+
# @see https://github.com/jruby/jruby/issues/1196
|
|
211
|
+
# @see https://github.com/simplecov-ruby/simplecov/issues/420
|
|
212
|
+
# @see https://github.com/simplecov-ruby/simplecov/issues/86
|
|
213
|
+
def warn_if_jruby_full_trace_disabled
|
|
214
|
+
return unless defined?(JRUBY_VERSION) && defined?(JRuby) # simplecov:disable — JRuby-only branch
|
|
413
215
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
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
|
|
216
|
+
# simplecov:disable — JRuby-only branches; unreachable from CRuby
|
|
217
|
+
# `org` is JRuby's Java-package entry point; it does not exist on
|
|
218
|
+
# CRuby, so no RBS declaration can be truthful here.
|
|
219
|
+
return if org.jruby.RubyInstanceConfig.FULL_TRACE_ENABLED # steep:ignore NoMethod
|
|
433
220
|
|
|
434
|
-
|
|
435
|
-
|
|
221
|
+
warn 'Coverage may be inaccurate; set the "--debug" command line option, ' \
|
|
222
|
+
'or do JRUBY_OPTS="--debug" ' \
|
|
223
|
+
'or set the "debug.fullTrace=true" option in your .jrubyrc'
|
|
224
|
+
# simplecov:enable
|
|
436
225
|
end
|
|
437
226
|
end
|
|
438
227
|
end
|
|
439
228
|
|
|
440
|
-
# requires are down here
|
|
441
|
-
require "set"
|
|
229
|
+
# requires are down here for a load order reason I'm not sure what it is about
|
|
442
230
|
require "forwardable"
|
|
231
|
+
require_relative "simplecov/color"
|
|
232
|
+
require_relative "simplecov/deprecation"
|
|
443
233
|
require_relative "simplecov/configuration"
|
|
444
234
|
SimpleCov.extend SimpleCov::Configuration
|
|
445
235
|
require_relative "simplecov/coverage_statistics"
|
|
236
|
+
require_relative "simplecov/coverage_violations"
|
|
446
237
|
require_relative "simplecov/exit_codes"
|
|
447
238
|
require_relative "simplecov/profiles"
|
|
448
239
|
require_relative "simplecov/source_file/line"
|
|
449
240
|
require_relative "simplecov/source_file/branch"
|
|
241
|
+
require_relative "simplecov/source_file/method"
|
|
450
242
|
require_relative "simplecov/source_file"
|
|
451
243
|
require_relative "simplecov/file_list"
|
|
452
244
|
require_relative "simplecov/result"
|
|
@@ -455,16 +247,22 @@ require_relative "simplecov/formatter"
|
|
|
455
247
|
require_relative "simplecov/last_run"
|
|
456
248
|
require_relative "simplecov/lines_classifier"
|
|
457
249
|
require_relative "simplecov/result_merger"
|
|
250
|
+
require_relative "simplecov/parallel_adapters"
|
|
458
251
|
require_relative "simplecov/command_guesser"
|
|
459
252
|
require_relative "simplecov/version"
|
|
460
253
|
require_relative "simplecov/result_adapter"
|
|
461
254
|
require_relative "simplecov/combine"
|
|
462
255
|
require_relative "simplecov/combine/branches_combiner"
|
|
256
|
+
require_relative "simplecov/combine/methods_combiner"
|
|
463
257
|
require_relative "simplecov/combine/files_combiner"
|
|
464
258
|
require_relative "simplecov/combine/lines_combiner"
|
|
465
259
|
require_relative "simplecov/combine/results_combiner"
|
|
466
260
|
require_relative "simplecov/useless_results_remover"
|
|
467
261
|
require_relative "simplecov/simulate_coverage"
|
|
262
|
+
require_relative "simplecov/result_processing"
|
|
263
|
+
require_relative "simplecov/exit_handling"
|
|
264
|
+
require_relative "simplecov/parallel_coordination"
|
|
468
265
|
|
|
469
266
|
# Load default config
|
|
267
|
+
# simplecov:disable — env-var only set by aruba feature tests
|
|
470
268
|
require_relative "simplecov/defaults" unless ENV["SIMPLECOV_NO_DEFAULTS"]
|