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
data/lib/simplecov.rb
CHANGED
|
@@ -1,470 +1,275 @@
|
|
|
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
62
|
|
|
59
|
-
|
|
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
|
|
60
68
|
end
|
|
61
69
|
|
|
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!
|
|
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
|
|
95
74
|
end
|
|
96
75
|
|
|
97
76
|
#
|
|
98
|
-
#
|
|
99
|
-
#
|
|
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
|
-
|
|
77
|
+
# Sets up SimpleCov to run against your project. See README for
|
|
78
|
+
# the full DSL, or:
|
|
120
79
|
#
|
|
121
|
-
#
|
|
122
|
-
#
|
|
80
|
+
# SimpleCov.start
|
|
81
|
+
# SimpleCov.start 'rails' # using a profile
|
|
82
|
+
# SimpleCov.start { add_filter 'test' } # with a config block
|
|
123
83
|
#
|
|
124
|
-
def
|
|
125
|
-
|
|
126
|
-
end
|
|
84
|
+
def start(profile = nil, &)
|
|
85
|
+
warn_about_start_in_dot_simplecov if @autoloading_dot_simplecov
|
|
127
86
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
def filtered(files)
|
|
132
|
-
result = files.clone
|
|
133
|
-
filters.each do |filter|
|
|
134
|
-
result = result.reject { |source_file| filter.matches?(source_file) }
|
|
135
|
-
end
|
|
136
|
-
SimpleCov::FileList.new result
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
#
|
|
140
|
-
# Applies the configured groups to the given array of SimpleCov::SourceFile items
|
|
141
|
-
#
|
|
142
|
-
def grouped(files)
|
|
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
|
|
153
|
-
end
|
|
154
|
-
|
|
155
|
-
#
|
|
156
|
-
# Applies the profile of given name on SimpleCov configuration
|
|
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
|
-
|
|
167
|
-
#
|
|
168
|
-
# Clear out the previously cached .result. Primarily useful in testing
|
|
169
|
-
#
|
|
170
|
-
def clear_result
|
|
171
|
-
@result = nil
|
|
172
|
-
end
|
|
173
|
-
|
|
174
|
-
def at_exit_behavior
|
|
175
|
-
# If we are in a different process than called start, don't interfere.
|
|
176
|
-
return if SimpleCov.pid != Process.pid
|
|
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
|
|
227
|
-
|
|
228
|
-
# @api private
|
|
229
|
-
def ready_to_process_results?
|
|
230
|
-
final_result_process? && result?
|
|
231
|
-
end
|
|
129
|
+
def install_at_exit_hook
|
|
130
|
+
return if @at_exit_hook_installed
|
|
232
131
|
|
|
233
|
-
|
|
234
|
-
|
|
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?
|
|
235
140
|
|
|
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
|
|
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
145
|
#
|
|
266
|
-
#
|
|
267
|
-
#
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
end
|
|
272
|
-
|
|
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.
|
|
273
151
|
#
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
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
|
|
278
160
|
|
|
279
|
-
|
|
280
|
-
|
|
161
|
+
# Select the parallel adapter and generate identities before any forks.
|
|
162
|
+
SimpleCov::RunIdentity.prepare
|
|
281
163
|
|
|
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
|
|
164
|
+
@result = nil
|
|
165
|
+
self.pid = Process.pid
|
|
166
|
+
self.process_start_time = Time.now
|
|
291
167
|
|
|
292
|
-
|
|
293
|
-
# @api private
|
|
294
|
-
#
|
|
295
|
-
# Rounding down to be extra strict, see #679
|
|
296
|
-
def round_coverage(coverage)
|
|
297
|
-
coverage.floor(2)
|
|
168
|
+
start_coverage_measurement
|
|
298
169
|
end
|
|
299
170
|
|
|
300
171
|
private
|
|
301
172
|
|
|
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
173
|
#
|
|
309
|
-
# Trigger Coverage.start
|
|
310
|
-
#
|
|
311
|
-
#
|
|
312
|
-
# With Negative branch it supports only line coverage measurement type
|
|
174
|
+
# Trigger Coverage.start with the configured criteria. Every supported
|
|
175
|
+
# runtime (CRuby >= 3.2, JRuby >= 10, TruffleRuby >= 22) accepts the
|
|
176
|
+
# criteria-hash form, so no compatibility fallback is needed.
|
|
313
177
|
#
|
|
314
178
|
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?
|
|
179
|
+
start_arguments = coverage_criteria.to_h do |criterion|
|
|
180
|
+
[CRITERION_TO_RUBY_COVERAGE.fetch(criterion), true]
|
|
346
181
|
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
182
|
|
|
354
183
|
start_arguments[:eval] = true if coverage_for_eval_enabled?
|
|
355
184
|
|
|
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)
|
|
185
|
+
Coverage.start(**start_arguments) unless Coverage.running?
|
|
365
186
|
end
|
|
366
187
|
|
|
367
|
-
#
|
|
368
|
-
#
|
|
369
|
-
#
|
|
370
|
-
#
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
end
|
|
378
|
-
end
|
|
188
|
+
# `Rake::TestTask` runs `ruby -e 'require "minitest/autorun"; ...'`,
|
|
189
|
+
# which means Minitest's at_exit registers before SimpleCov's. Since
|
|
190
|
+
# at_exit fires LIFO, SimpleCov's hook would otherwise run *before*
|
|
191
|
+
# Minitest gets a chance to invoke the tests — and format an empty
|
|
192
|
+
# resultset. When we can see that Minitest is loaded and its autorun
|
|
193
|
+
# is armed, route the report through `Minitest.after_run` instead,
|
|
194
|
+
# which fires after the suite completes. See issues #1099 and #1112.
|
|
195
|
+
def minitest_autorun_pending?
|
|
196
|
+
return false unless defined?(Minitest) && Minitest.respond_to?(:after_run)
|
|
197
|
+
return false unless Minitest.class_variable_defined?(:@@installed_at_exit)
|
|
379
198
|
|
|
380
|
-
|
|
199
|
+
Minitest.class_variable_get(:@@installed_at_exit)
|
|
381
200
|
end
|
|
382
201
|
|
|
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
|
|
202
|
+
def defer_to_minitest_after_run
|
|
203
|
+
self.external_at_exit = true
|
|
204
|
+
Minitest.after_run { SimpleCov.at_exit_behavior }
|
|
392
205
|
end
|
|
393
206
|
|
|
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
|
|
207
|
+
# JRuby coverage data is unreliable unless full-trace mode is enabled.
|
|
208
|
+
# @see https://github.com/jruby/jruby/issues/1196
|
|
209
|
+
# @see https://github.com/simplecov-ruby/simplecov/issues/420
|
|
210
|
+
# @see https://github.com/simplecov-ruby/simplecov/issues/86
|
|
211
|
+
def warn_if_jruby_full_trace_disabled
|
|
212
|
+
return unless defined?(JRUBY_VERSION) && defined?(JRuby) # simplecov:disable — JRuby-only branch
|
|
413
213
|
|
|
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
|
|
214
|
+
# simplecov:disable — JRuby-only branches; unreachable from CRuby
|
|
215
|
+
# `org` is JRuby's Java-package entry point; it does not exist on
|
|
216
|
+
# CRuby, so no RBS declaration can be truthful here.
|
|
217
|
+
return if org.jruby.RubyInstanceConfig.FULL_TRACE_ENABLED # steep:ignore NoMethod
|
|
433
218
|
|
|
434
|
-
|
|
435
|
-
|
|
219
|
+
warn 'Coverage may be inaccurate; set the "--debug" command line option, ' \
|
|
220
|
+
'or do JRUBY_OPTS="--debug" ' \
|
|
221
|
+
'or set the "debug.fullTrace=true" option in your .jrubyrc'
|
|
222
|
+
# simplecov:enable
|
|
436
223
|
end
|
|
437
224
|
end
|
|
438
225
|
end
|
|
439
226
|
|
|
440
|
-
# requires are down here
|
|
441
|
-
require "set"
|
|
227
|
+
# requires are down here for a load order reason I'm not sure what it is about
|
|
442
228
|
require "forwardable"
|
|
229
|
+
require_relative "simplecov/color"
|
|
230
|
+
require_relative "simplecov/deprecation"
|
|
231
|
+
require_relative "simplecov/group_names"
|
|
443
232
|
require_relative "simplecov/configuration"
|
|
444
233
|
SimpleCov.extend SimpleCov::Configuration
|
|
445
234
|
require_relative "simplecov/coverage_statistics"
|
|
235
|
+
require_relative "simplecov/coverage_violations"
|
|
446
236
|
require_relative "simplecov/exit_codes"
|
|
447
237
|
require_relative "simplecov/profiles"
|
|
448
238
|
require_relative "simplecov/source_file/line"
|
|
449
239
|
require_relative "simplecov/source_file/branch"
|
|
240
|
+
require_relative "simplecov/source_file/method"
|
|
450
241
|
require_relative "simplecov/source_file"
|
|
451
242
|
require_relative "simplecov/file_list"
|
|
452
243
|
require_relative "simplecov/result"
|
|
453
244
|
require_relative "simplecov/filter"
|
|
454
245
|
require_relative "simplecov/formatter"
|
|
455
246
|
require_relative "simplecov/last_run"
|
|
247
|
+
require_relative "simplecov/report_stamp"
|
|
456
248
|
require_relative "simplecov/lines_classifier"
|
|
457
249
|
require_relative "simplecov/result_merger"
|
|
250
|
+
require_relative "simplecov/parallel_result_merger"
|
|
251
|
+
require_relative "simplecov/parallel_adapters"
|
|
252
|
+
require_relative "simplecov/run_identity"
|
|
253
|
+
SimpleCov.extend SimpleCov::RunIdentity::Accessors
|
|
458
254
|
require_relative "simplecov/command_guesser"
|
|
459
255
|
require_relative "simplecov/version"
|
|
460
256
|
require_relative "simplecov/result_adapter"
|
|
461
257
|
require_relative "simplecov/combine"
|
|
258
|
+
require_relative "simplecov/combine/identity_interner"
|
|
462
259
|
require_relative "simplecov/combine/branches_combiner"
|
|
463
|
-
require_relative "simplecov/combine/
|
|
260
|
+
require_relative "simplecov/combine/methods_combiner"
|
|
464
261
|
require_relative "simplecov/combine/lines_combiner"
|
|
262
|
+
require_relative "simplecov/combine/coverage_accumulator"
|
|
465
263
|
require_relative "simplecov/combine/results_combiner"
|
|
466
264
|
require_relative "simplecov/useless_results_remover"
|
|
467
265
|
require_relative "simplecov/simulate_coverage"
|
|
266
|
+
require_relative "simplecov/unloaded_file_injector"
|
|
267
|
+
require_relative "simplecov/result_processing"
|
|
268
|
+
require_relative "simplecov/exit_handling"
|
|
269
|
+
require_relative "simplecov/report_deferral"
|
|
270
|
+
require_relative "simplecov/parallel_coordination"
|
|
468
271
|
|
|
469
272
|
# Load default config
|
|
273
|
+
# simplecov:disable — env-var never set in the dogfooded test process
|
|
274
|
+
# (sandbox fixture subprocesses set it via simplecov/no_defaults)
|
|
470
275
|
require_relative "simplecov/defaults" unless ENV["SIMPLECOV_NO_DEFAULTS"]
|