simplecov 0.21.2 → 1.0.0.rc1

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.
Files changed (113) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +90 -0
  3. data/LICENSE +1 -1
  4. data/README.md +1018 -508
  5. data/doc/alternate-formatters.md +0 -5
  6. data/doc/commercial-services.md +5 -5
  7. data/exe/simplecov +11 -0
  8. data/lib/minitest/simplecov_plugin.rb +13 -5
  9. data/lib/simplecov/autostart.rb +11 -0
  10. data/lib/simplecov/cli/clean.rb +47 -0
  11. data/lib/simplecov/cli/coverage.rb +91 -0
  12. data/lib/simplecov/cli/diff.rb +151 -0
  13. data/lib/simplecov/cli/dotfile.rb +100 -0
  14. data/lib/simplecov/cli/merge.rb +116 -0
  15. data/lib/simplecov/cli/open.rb +50 -0
  16. data/lib/simplecov/cli/report.rb +84 -0
  17. data/lib/simplecov/cli/run.rb +36 -0
  18. data/lib/simplecov/cli/serve.rb +139 -0
  19. data/lib/simplecov/cli/uncovered.rb +107 -0
  20. data/lib/simplecov/cli.rb +150 -0
  21. data/lib/simplecov/color.rb +74 -0
  22. data/lib/simplecov/combine/branches_combiner.rb +3 -2
  23. data/lib/simplecov/combine/files_combiner.rb +7 -1
  24. data/lib/simplecov/combine/lines_combiner.rb +19 -17
  25. data/lib/simplecov/combine/methods_combiner.rb +26 -0
  26. data/lib/simplecov/combine/results_combiner.rb +5 -4
  27. data/lib/simplecov/command_guesser.rb +46 -32
  28. data/lib/simplecov/configuration/coverage.rb +171 -0
  29. data/lib/simplecov/configuration/coverage_criteria.rb +156 -0
  30. data/lib/simplecov/configuration/filters.rb +195 -0
  31. data/lib/simplecov/configuration/formatting.rb +119 -0
  32. data/lib/simplecov/configuration/ignored_entries.rb +63 -0
  33. data/lib/simplecov/configuration/merging.rb +74 -0
  34. data/lib/simplecov/configuration/thresholds.rb +174 -0
  35. data/lib/simplecov/configuration.rb +79 -386
  36. data/lib/simplecov/coverage_statistics.rb +12 -9
  37. data/lib/simplecov/coverage_violations.rb +148 -0
  38. data/lib/simplecov/defaults.rb +27 -20
  39. data/lib/simplecov/directive.rb +162 -0
  40. data/lib/simplecov/exit_codes/exit_code_handling.rb +8 -2
  41. data/lib/simplecov/exit_codes/maximum_coverage_drop_check.rb +19 -57
  42. data/lib/simplecov/exit_codes/maximum_overall_coverage_check.rb +45 -0
  43. data/lib/simplecov/exit_codes/minimum_coverage_by_file_check.rb +17 -27
  44. data/lib/simplecov/exit_codes/minimum_coverage_by_group_check.rb +41 -0
  45. data/lib/simplecov/exit_codes/minimum_overall_coverage_check.rb +38 -21
  46. data/lib/simplecov/exit_codes.rb +3 -0
  47. data/lib/simplecov/exit_handling.rb +158 -0
  48. data/lib/simplecov/file_list.rb +61 -17
  49. data/lib/simplecov/filter.rb +69 -24
  50. data/lib/simplecov/formatter/base.rb +101 -0
  51. data/lib/simplecov/formatter/html_formatter/public/application.css +1 -0
  52. data/lib/simplecov/formatter/html_formatter/public/application.js +18 -0
  53. data/lib/simplecov/formatter/html_formatter/public/favicon_green.png +0 -0
  54. data/lib/simplecov/formatter/html_formatter/public/favicon_red.png +0 -0
  55. data/lib/simplecov/formatter/html_formatter/public/favicon_yellow.png +0 -0
  56. data/lib/simplecov/formatter/html_formatter/public/index.html +56 -0
  57. data/lib/simplecov/formatter/html_formatter.rb +79 -0
  58. data/lib/simplecov/formatter/json_formatter/errors_formatter.rb +84 -0
  59. data/lib/simplecov/formatter/json_formatter/result_hash_formatter.rb +127 -0
  60. data/lib/simplecov/formatter/json_formatter/source_file_formatter.rb +99 -0
  61. data/lib/simplecov/formatter/json_formatter.rb +77 -0
  62. data/lib/simplecov/formatter/multi_formatter.rb +4 -5
  63. data/lib/simplecov/formatter/simple_formatter.rb +9 -11
  64. data/lib/simplecov/formatter.rb +4 -0
  65. data/lib/simplecov/last_run.rb +10 -3
  66. data/lib/simplecov/lines_classifier.rb +26 -13
  67. data/lib/simplecov/load_global_config.rb +9 -4
  68. data/lib/simplecov/parallel_adapters/base.rb +51 -0
  69. data/lib/simplecov/parallel_adapters/generic.rb +42 -0
  70. data/lib/simplecov/parallel_adapters/parallel_tests.rb +77 -0
  71. data/lib/simplecov/parallel_adapters.rb +83 -0
  72. data/lib/simplecov/parallel_coordination.rb +95 -0
  73. data/lib/simplecov/process.rb +20 -14
  74. data/lib/simplecov/profiles/bundler_filter.rb +1 -1
  75. data/lib/simplecov/profiles/hidden_filter.rb +1 -1
  76. data/lib/simplecov/profiles/rails.rb +24 -10
  77. data/lib/simplecov/profiles/root_filter.rb +6 -5
  78. data/lib/simplecov/profiles/strict.rb +32 -0
  79. data/lib/simplecov/profiles/test_frameworks.rb +1 -4
  80. data/lib/simplecov/profiles.rb +32 -3
  81. data/lib/simplecov/result/missing_source_files_reporter.rb +49 -0
  82. data/lib/simplecov/result/source_file_builder.rb +51 -0
  83. data/lib/simplecov/result.rb +97 -19
  84. data/lib/simplecov/result_adapter.rb +68 -6
  85. data/lib/simplecov/result_merger/legacy_format_adapter.rb +28 -0
  86. data/lib/simplecov/result_merger/resultset_file.rb +38 -0
  87. data/lib/simplecov/result_merger/resultset_store.rb +50 -0
  88. data/lib/simplecov/result_merger.rb +46 -90
  89. data/lib/simplecov/result_processing.rb +162 -0
  90. data/lib/simplecov/simulate_coverage.rb +54 -8
  91. data/lib/simplecov/source_file/branch.rb +1 -3
  92. data/lib/simplecov/source_file/branch_builder.rb +114 -0
  93. data/lib/simplecov/source_file/builder_context.rb +28 -0
  94. data/lib/simplecov/source_file/line.rb +7 -2
  95. data/lib/simplecov/source_file/line_builder.rb +43 -0
  96. data/lib/simplecov/source_file/method.rb +52 -0
  97. data/lib/simplecov/source_file/method_builder.rb +58 -0
  98. data/lib/simplecov/source_file/ruby_data_parser.rb +88 -0
  99. data/lib/simplecov/source_file/skip_chunks.rb +77 -0
  100. data/lib/simplecov/source_file/source_loader.rb +63 -0
  101. data/lib/simplecov/source_file/statistics.rb +57 -0
  102. data/lib/simplecov/source_file.rb +66 -226
  103. data/lib/simplecov/static_coverage_extractor/visitor.rb +193 -0
  104. data/lib/simplecov/static_coverage_extractor.rb +111 -0
  105. data/lib/simplecov/useless_results_remover.rb +16 -7
  106. data/lib/simplecov/version.rb +1 -1
  107. data/lib/simplecov-html.rb +4 -0
  108. data/lib/simplecov.rb +133 -377
  109. data/lib/simplecov_json_formatter.rb +4 -0
  110. data/schemas/coverage-v1.0.schema.json +300 -0
  111. data/schemas/coverage.schema.json +300 -0
  112. metadata +88 -56
  113. data/lib/simplecov/default_formatter.rb +0 -20
@@ -1,18 +1,27 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SimpleCov
4
- #
5
- # Select the files that related to working scope directory of SimpleCov
6
- #
4
+ # Drop coverage entries whose paths live outside `SimpleCov.root` so the
5
+ # report only reflects the project's own source. Vendored gems, stdlib
6
+ # files, and anything else that happens to have been touched during the
7
+ # run never make it into the formatted result.
7
8
  module UselessResultsRemover
8
9
  def self.call(coverage_result)
9
- coverage_result.select do |path, _coverage|
10
- path =~ root_regx
11
- end
10
+ coverage_result.select { |path, _coverage| path.match?(root_regex) }
11
+ end
12
+
13
+ # The `/i` flag covers case-insensitive matches on Windows / macOS-HFS+
14
+ # where the on-disk path's case can differ from `SimpleCov.root`'s.
15
+ def self.root_regex
16
+ root = SimpleCov.root
17
+ return @root_regex if root == @root_regex_root
18
+
19
+ @root_regex_root = root
20
+ @root_regex = /\A#{Regexp.escape(root.chomp(File::SEPARATOR) + File::SEPARATOR)}/i
12
21
  end
13
22
 
14
23
  def self.root_regx
15
- @root_regx ||= /\A#{Regexp.escape(SimpleCov.root + File::SEPARATOR)}/i.freeze
24
+ root_regex
16
25
  end
17
26
  end
18
27
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SimpleCov
4
- VERSION = "0.21.2"
4
+ VERSION = "1.0.0.rc1"
5
5
  end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Backward-compatibility shim: simplecov-html is now part of simplecov.
4
+ require_relative "simplecov/formatter/html_formatter"
data/lib/simplecov.rb CHANGED
@@ -1,450 +1,200 @@
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
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
+
23
11
  class << self
24
- attr_accessor :running, :pid
12
+ CRITERION_TO_RUBY_COVERAGE = {
13
+ branch: :branches,
14
+ line: :lines,
15
+ method: :methods,
16
+ oneshot_line: :oneshot_lines
17
+ }.freeze
25
18
 
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
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
24
+ # Should we take care of at_exit behavior or something else? Used by the
25
+ # minitest plugin. See lib/minitest/simplecov_plugin.rb.
28
26
  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
27
 
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
28
+ # `:oneshot_line` data is folded into the `:line` bucket of
29
+ # `coverage_statistics` by `ResultAdapter`, so use `:line` to look
30
+ # up stats for either criterion.
31
+ def coverage_statistics_key(criterion)
32
+ criterion == :oneshot_line ? :line : criterion
118
33
  end
119
34
 
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
-
128
- #
129
- # Applies the configured filters to the given array of SimpleCov::SourceFile items
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
35
+ # Coerce to a proper boolean so rspec-mocks 4's predicate matcher
36
+ # (`expect(...).not_to be_external_at_exit`) accepts the result.
37
+ def external_at_exit?
38
+ !!@external_at_exit
153
39
  end
154
40
 
155
41
  #
156
- # Applies the profile of given name on SimpleCov configuration
42
+ # Sets up SimpleCov to run against your project. See README for
43
+ # the full DSL, or:
157
44
  #
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
45
+ # SimpleCov.start
46
+ # SimpleCov.start 'rails' # using a profile
47
+ # SimpleCov.start { add_filter 'test' } # with a config block
169
48
  #
170
- def clear_result
171
- @result = nil
172
- end
49
+ def start(profile = nil, &)
50
+ warn_about_start_in_dot_simplecov if @autoloading_dot_simplecov
173
51
 
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
52
+ initial_setup(profile, &)
53
+ start_tracking
54
+ install_at_exit_hook
180
55
  end
181
56
 
182
57
  # @api private
183
58
  #
184
- # Called from at_exit block
185
- #
186
- def run_exit_tasks!
187
- error_exit_status = exit_status_from_exception
188
-
189
- at_exit.call
190
-
191
- exit_and_report_previous_error(error_exit_status) if previous_error?(error_exit_status)
192
- process_results_and_report_error if ready_to_process_results?
59
+ # Mark the duration of a `.simplecov` auto-load so any `SimpleCov.start`
60
+ # call inside the file can warn about the impending migration to a
61
+ # config-only file. Tracking still begins for backward compatibility;
62
+ # the warning is the cue to move `SimpleCov.start` into a test helper.
63
+ # See #581.
64
+ def with_dot_simplecov_autoload
65
+ previous = @autoloading_dot_simplecov
66
+ @autoloading_dot_simplecov = true
67
+ yield
68
+ ensure
69
+ @autoloading_dot_simplecov = previous
193
70
  end
194
71
 
195
- #
196
- # @api private
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
72
+ def warn_about_start_in_dot_simplecov
73
+ return if @dot_simplecov_start_warned
204
74
 
205
- if @exit_exception.is_a?(SystemExit)
206
- @exit_exception.status
207
- else
208
- SimpleCov::ExitCodes::EXCEPTION
209
- end
210
- end
211
-
212
- # @api private
213
- def previous_error?(error_exit_status)
214
- # Normally it'd be enough to check for previous error but when running test_unit
215
- # status is 0
216
- error_exit_status && error_exit_status != SimpleCov::ExitCodes::SUCCESS
75
+ @dot_simplecov_start_warned = true
76
+ warn "[DEPRECATION] Calling `SimpleCov.start` from `.simplecov` is deprecated and will " \
77
+ "be removed in a future release. `.simplecov` should contain configuration only; " \
78
+ "move the `SimpleCov.start` call into your `spec_helper.rb` / `test_helper.rb`. " \
79
+ "Coverage tracking still begins for backward compatibility, but a future release " \
80
+ "will require the explicit `SimpleCov.start` from a test helper. " \
81
+ "See https://github.com/simplecov-ruby/simplecov/issues/581."
217
82
  end
218
83
 
219
84
  #
220
- # @api private
85
+ # Install the at_exit hook that formats results and runs exit-code
86
+ # checks. `SimpleCov.start` calls this automatically. Idempotent —
87
+ # safe to call multiple times. Callers that drive the formatting
88
+ # pipeline themselves (e.g., dogfood test setups) can skip it by
89
+ # using `start_tracking` directly instead of `start`.
221
90
  #
222
- # Thinking: Move this behavior earlier so if there was an error we do nothing?
223
- def exit_and_report_previous_error(exit_status)
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
91
+ def install_at_exit_hook
92
+ return if @at_exit_hook_installed
227
93
 
228
- # @api private
229
- def ready_to_process_results?
230
- final_result_process? && result?
231
- end
94
+ @at_exit_hook_installed = true
95
+ defer_to_minitest_after_run if minitest_autorun_pending?
96
+ Kernel.at_exit do
97
+ next if SimpleCov.external_at_exit?
232
98
 
233
- def process_results_and_report_error
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
99
+ SimpleCov.at_exit_behavior
240
100
  end
241
101
  end
242
102
 
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
103
  #
266
- # @api private
104
+ # Begin coverage tracking without applying configuration. Pairs with
105
+ # `SimpleCov.configure { ... }` for callers that want to separate
106
+ # the two — for example a dogfood test that has already started
107
+ # `Coverage` itself before requiring simplecov, but still wants the
108
+ # process_start_time / pid / fork-hook bookkeeping.
267
109
  #
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
- #
274
- # @api private
275
- #
276
- def wait_for_other_processes
277
- return unless defined?(ParallelTests) && final_result_process?
278
-
279
- ParallelTests.wait_for_other_processes_to_finish
280
- end
110
+ def start_tracking
111
+ require "coverage"
112
+ warn_if_jruby_full_trace_disabled
113
+ validate_coverage_criteria!
114
+ # simplecov:disable — fork-hook is enabled via SimpleCov.enable_for_subprocesses, off by default
115
+ require_relative "simplecov/process" if SimpleCov.enabled_for_subprocesses? &&
116
+ ::Process.respond_to?(:_fork)
117
+ # simplecov:enable
118
+
119
+ # Trigger adapter selection now so the (possibly lazy) parallel_tests
120
+ # gem load happens at start_tracking time rather than mid-suite.
121
+ # `current` is memoized; subsequent calls are cheap.
122
+ SimpleCov::ParallelAdapters.current
281
123
 
282
- #
283
- # @api private
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
124
+ @result = nil
125
+ self.pid = Process.pid
126
+ self.process_start_time = Time.now
291
127
 
292
- #
293
- # @api private
294
- #
295
- # Rounding down to be extra strict, see #679
296
- def round_coverage(coverage)
297
- coverage.floor(2)
128
+ start_coverage_measurement
298
129
  end
299
130
 
300
131
  private
301
132
 
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
133
  #
311
- # With Positive branch it supports all coverage measurement types
312
- # With Negative branch it supports only line coverage measurement type
134
+ # Trigger Coverage.start with the configured criteria. Every supported
135
+ # runtime (CRuby >= 3.1, JRuby >= 9.4, TruffleRuby >= 22) accepts the
136
+ # criteria-hash form, so no compatibility fallback is needed.
313
137
  #
314
138
  def start_coverage_measurement
315
- # This blog post gives a good run down of the coverage criterias introduced
316
- # in Ruby 2.5: https://blog.bigbinary.com/2018/04/11/ruby-2-5-supports-measuring-branch-and-method-coverages.html
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
139
+ start_arguments = coverage_criteria.to_h do |criterion|
140
+ [CRITERION_TO_RUBY_COVERAGE.fetch(criterion), true]
346
141
  end
347
- end
348
142
 
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
143
+ start_arguments[:eval] = true if coverage_for_eval_enabled?
353
144
 
354
- Coverage.start(start_arguments)
145
+ Coverage.start(start_arguments) unless Coverage.running?
355
146
  end
356
147
 
357
- CRITERION_TO_RUBY_COVERAGE = {
358
- branch: :branches,
359
- line: :lines
360
- }.freeze
361
- def lookup_corresponding_ruby_coverage_name(criterion)
362
- CRITERION_TO_RUBY_COVERAGE.fetch(criterion)
363
- end
364
-
365
- #
366
- # Finds files that were to be tracked but were not loaded and initializes
367
- # the line-by-line coverage to zero (if relevant) or nil (comments / whitespace etc).
368
- #
369
- def add_not_loaded_files(result)
370
- if tracked_files
371
- result = result.dup
372
- Dir[tracked_files].each do |file|
373
- absolute_path = File.expand_path(file)
374
- result[absolute_path] ||= SimulateCoverage.call(absolute_path)
375
- end
376
- end
148
+ # `Rake::TestTask` runs `ruby -e 'require "minitest/autorun"; ...'`,
149
+ # which means Minitest's at_exit registers before SimpleCov's. Since
150
+ # at_exit fires LIFO, SimpleCov's hook would otherwise run *before*
151
+ # Minitest gets a chance to invoke the tests — and format an empty
152
+ # resultset. When we can see that Minitest is loaded and its autorun
153
+ # is armed, route the report through `Minitest.after_run` instead,
154
+ # which fires after the suite completes. See issues #1099 and #1112.
155
+ def minitest_autorun_pending?
156
+ return false unless defined?(Minitest) && Minitest.respond_to?(:after_run)
157
+ return false unless Minitest.class_variable_defined?(:@@installed_at_exit)
377
158
 
378
- result
159
+ Minitest.class_variable_get(:@@installed_at_exit)
379
160
  end
380
161
 
381
- #
382
- # Call steps that handle process coverage result
383
- #
384
- # @return [Hash]
385
- #
386
- def process_coverage_result
387
- adapt_coverage_result
388
- remove_useless_results
389
- result_with_not_loaded_files
162
+ def defer_to_minitest_after_run
163
+ self.external_at_exit = true
164
+ Minitest.after_run { SimpleCov.at_exit_behavior }
390
165
  end
391
166
 
392
- #
393
- # Unite the result so it wouldn't matter what coverage type was called
394
- #
395
- # @return [Hash]
396
- #
397
- def adapt_coverage_result
398
- @result = SimpleCov::ResultAdapter.call(Coverage.result)
399
- end
400
-
401
- #
402
- # Filter coverage result
403
- # The result before filter also has result of coverage for files
404
- # are not related to the project like loaded gems coverage.
405
- #
406
- # @return [Hash]
407
- #
408
- def remove_useless_results
409
- @result = SimpleCov::UselessResultsRemover.call(@result)
410
- end
411
-
412
- #
413
- # Initialize result with files that are not included by coverage
414
- # and added inside the config block
415
- #
416
- # @return [Hash]
417
- #
418
- def result_with_not_loaded_files
419
- @result = SimpleCov::Result.new(add_not_loaded_files(@result))
420
- end
167
+ # JRuby coverage data is unreliable unless full-trace mode is enabled.
168
+ # @see https://github.com/jruby/jruby/issues/1196
169
+ # @see https://github.com/simplecov-ruby/simplecov/issues/420
170
+ # @see https://github.com/simplecov-ruby/simplecov/issues/86
171
+ def warn_if_jruby_full_trace_disabled
172
+ return unless defined?(JRUBY_VERSION) && defined?(JRuby) # simplecov:disable — JRuby-only branch
421
173
 
422
- # parallel_tests isn't always available, see: https://github.com/grosser/parallel_tests/issues/772
423
- def make_parallel_tests_available
424
- return if defined?(ParallelTests)
425
- return unless probably_running_parallel_tests?
426
-
427
- require "parallel_tests"
428
- rescue LoadError
429
- warn("SimpleCov guessed you were running inside parallel tests but couldn't load it. Please file a bug report with us!")
430
- end
174
+ # simplecov:disable JRuby-only branches; unreachable from CRuby
175
+ return if org.jruby.RubyInstanceConfig.FULL_TRACE_ENABLED
431
176
 
432
- def probably_running_parallel_tests?
433
- ENV["TEST_ENV_NUMBER"] && ENV["PARALLEL_TEST_GROUPS"]
177
+ warn 'Coverage may be inaccurate; set the "--debug" command line option, ' \
178
+ 'or do JRUBY_OPTS="--debug" ' \
179
+ 'or set the "debug.fullTrace=true" option in your .jrubyrc'
180
+ # simplecov:enable
434
181
  end
435
182
  end
436
183
  end
437
184
 
438
- # requires are down here here for a load order reason I'm not sure what it is about
185
+ # requires are down here for a load order reason I'm not sure what it is about
439
186
  require "set"
440
187
  require "forwardable"
188
+ require_relative "simplecov/color"
441
189
  require_relative "simplecov/configuration"
442
190
  SimpleCov.extend SimpleCov::Configuration
443
191
  require_relative "simplecov/coverage_statistics"
192
+ require_relative "simplecov/coverage_violations"
444
193
  require_relative "simplecov/exit_codes"
445
194
  require_relative "simplecov/profiles"
446
195
  require_relative "simplecov/source_file/line"
447
196
  require_relative "simplecov/source_file/branch"
197
+ require_relative "simplecov/source_file/method"
448
198
  require_relative "simplecov/source_file"
449
199
  require_relative "simplecov/file_list"
450
200
  require_relative "simplecov/result"
@@ -453,16 +203,22 @@ require_relative "simplecov/formatter"
453
203
  require_relative "simplecov/last_run"
454
204
  require_relative "simplecov/lines_classifier"
455
205
  require_relative "simplecov/result_merger"
206
+ require_relative "simplecov/parallel_adapters"
456
207
  require_relative "simplecov/command_guesser"
457
208
  require_relative "simplecov/version"
458
209
  require_relative "simplecov/result_adapter"
459
210
  require_relative "simplecov/combine"
460
211
  require_relative "simplecov/combine/branches_combiner"
212
+ require_relative "simplecov/combine/methods_combiner"
461
213
  require_relative "simplecov/combine/files_combiner"
462
214
  require_relative "simplecov/combine/lines_combiner"
463
215
  require_relative "simplecov/combine/results_combiner"
464
216
  require_relative "simplecov/useless_results_remover"
465
217
  require_relative "simplecov/simulate_coverage"
218
+ require_relative "simplecov/result_processing"
219
+ require_relative "simplecov/exit_handling"
220
+ require_relative "simplecov/parallel_coordination"
466
221
 
467
222
  # Load default config
223
+ # simplecov:disable — env-var only set by aruba feature tests
468
224
  require_relative "simplecov/defaults" unless ENV["SIMPLECOV_NO_DEFAULTS"]
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Backward-compatibility shim: simplecov_json_formatter is now part of simplecov.
4
+ require_relative "simplecov/formatter/json_formatter"