simplecov 1.0.0.rc1 → 1.0.0.rc2
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/CHANGELOG.md +8 -0
- data/lib/simplecov/configuration/coverage_criteria.rb +2 -2
- data/lib/simplecov/configuration/filters.rb +8 -6
- data/lib/simplecov/configuration/formatting.rb +4 -4
- data/lib/simplecov/configuration/merging.rb +4 -4
- data/lib/simplecov/configuration/thresholds.rb +4 -4
- data/lib/simplecov/configuration.rb +9 -4
- data/lib/simplecov/deprecation.rb +47 -0
- data/lib/simplecov/process.rb +7 -1
- data/lib/simplecov/result_merger.rb +8 -0
- data/lib/simplecov/source_file.rb +4 -4
- data/lib/simplecov/version.rb +1 -1
- data/lib/simplecov.rb +17 -0
- metadata +5 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 95cc757bf172ce50cd60e636048c88e30fade408c962d8fe8c9478465b6b2d67
|
|
4
|
+
data.tar.gz: 9ee4b98d8f3f790289415b03c3e37c436b32d1e2a9d193fd435dfdb966d4b658
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 719bcdfee0e3e79de52e7da4fdd955d85416b2c33c3b8bcd437d13187b9d883c6430ea55e0d52ca17c392cfe4e506f6a433278d5d285091858702bd669eb43bd
|
|
7
|
+
data.tar.gz: 4e70c6fabe5ed02ea4ece1ca811434c96b760e871507cc607a05af64710a9f0c14ee87c16dbcf82d19cdaaf23f3896d78ea0500e051130dbc15b7c6046e4b6b8
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
1.0.0.rc2 (2026-06-10)
|
|
2
|
+
======================
|
|
3
|
+
|
|
4
|
+
## Bugfixes
|
|
5
|
+
* Forked subprocesses (for example Rails' `parallelize`) are now named by a stable per-run serial rather than the child's OS process id. Because the pid changed every run, a re-run's worker results were never named the same as the previous run's and so never overwrote them. They accumulated in `.resultset.json` until `merge_timeout` dropped them, and while several runs sat inside that window together SimpleCov merged them all. When the set of files had drifted between those runs (a deleted file, a changed filter) the stale results leaked into the report, inflating the denominator and changing the coverage percentage from one run to the next. The serial sequence is identical from one run to the next, so a re-run's workers now overwrite the previous run's entries and the resultset stays bounded. See #1171.
|
|
6
|
+
* The "Excluded N result(s) older than `merge_timeout`" warning is now emitted at most once, from the reporting process, instead of once per forked worker. Every worker merges the resultset too, and the default `at_fork` sets `print_errors false` for them, but this one warning did not honor the flag, so an eight-worker run printed eight copies. See #1171.
|
|
7
|
+
* Legacy-API deprecation warnings (`track_files`, `add_filter`, `add_group`, and the rest) are now deduplicated by call site and emitted at most once per source location. A deprecated method called in a loop, or a configuration block re-evaluated once per parallel worker or spec file, previously repeated the same notice until the surrounding output was unreadable. See #1204.
|
|
8
|
+
|
|
1
9
|
1.0.0.rc1 (2026-06-02)
|
|
2
10
|
======================
|
|
3
11
|
|
|
@@ -110,8 +110,8 @@ module SimpleCov
|
|
|
110
110
|
|
|
111
111
|
# DEPRECATED: prefer `enable_coverage :eval`.
|
|
112
112
|
def enable_coverage_for_eval
|
|
113
|
-
warn
|
|
114
|
-
|
|
113
|
+
SimpleCov::Deprecation.warn("`SimpleCov.enable_coverage_for_eval` is deprecated. " \
|
|
114
|
+
"Replace with `SimpleCov.enable_coverage :eval`.")
|
|
115
115
|
enable_eval_coverage
|
|
116
116
|
end
|
|
117
117
|
|
|
@@ -58,8 +58,8 @@ module SimpleCov
|
|
|
58
58
|
# historical `track_files` behavior) and restricts the report to the
|
|
59
59
|
# matching set.
|
|
60
60
|
def track_files(glob)
|
|
61
|
-
warn
|
|
62
|
-
|
|
61
|
+
SimpleCov::Deprecation.warn("`SimpleCov.track_files` is deprecated. " \
|
|
62
|
+
"#{track_files_replacement_hint(glob)}")
|
|
63
63
|
@tracked_files = glob
|
|
64
64
|
end
|
|
65
65
|
|
|
@@ -102,8 +102,8 @@ module SimpleCov
|
|
|
102
102
|
# DEPRECATED: alias for `skip`. Same matcher grammar, identical behavior.
|
|
103
103
|
def add_filter(filter_argument = nil, &block)
|
|
104
104
|
example = block ? "`SimpleCov.skip { ... }`" : "`SimpleCov.skip #{filter_argument.inspect}`"
|
|
105
|
-
warn
|
|
106
|
-
|
|
105
|
+
SimpleCov::Deprecation.warn("`SimpleCov.add_filter` is deprecated. " \
|
|
106
|
+
"Replace with `SimpleCov.skip` (same arguments, same behavior). Example: #{example}.")
|
|
107
107
|
skip(filter_argument, &block)
|
|
108
108
|
end
|
|
109
109
|
|
|
@@ -141,8 +141,10 @@ module SimpleCov
|
|
|
141
141
|
else
|
|
142
142
|
"`SimpleCov.group #{group_name.inspect}, #{filter_argument.inspect}`"
|
|
143
143
|
end
|
|
144
|
-
|
|
145
|
-
|
|
144
|
+
SimpleCov::Deprecation.warn(
|
|
145
|
+
"`SimpleCov.add_group` is deprecated. " \
|
|
146
|
+
"Replace with `SimpleCov.group` (same arguments, same behavior). Example: #{example}."
|
|
147
|
+
)
|
|
146
148
|
group(group_name, filter_argument, &block)
|
|
147
149
|
end
|
|
148
150
|
|
|
@@ -89,8 +89,8 @@ module SimpleCov
|
|
|
89
89
|
|
|
90
90
|
# DEPRECATED: alias for `print_errors`. Same value, same behavior.
|
|
91
91
|
def print_error_status
|
|
92
|
-
warn
|
|
93
|
-
|
|
92
|
+
SimpleCov::Deprecation.warn("`SimpleCov.print_error_status` is deprecated. " \
|
|
93
|
+
"Replace with `SimpleCov.print_errors` (same value).")
|
|
94
94
|
defined?(@print_error_status) ? @print_error_status : true
|
|
95
95
|
end
|
|
96
96
|
|
|
@@ -101,8 +101,8 @@ module SimpleCov
|
|
|
101
101
|
# be removed in a future release.
|
|
102
102
|
#
|
|
103
103
|
def nocov_token(nocov_token = nil)
|
|
104
|
-
warn
|
|
105
|
-
|
|
104
|
+
SimpleCov::Deprecation.warn("`SimpleCov.nocov_token` and `SimpleCov.skip_token` are deprecated. " \
|
|
105
|
+
"Replace with `# simplecov:disable` / `# simplecov:enable` block comments.")
|
|
106
106
|
current_nocov_token(nocov_token)
|
|
107
107
|
end
|
|
108
108
|
alias skip_token nocov_token
|
|
@@ -36,8 +36,8 @@ module SimpleCov
|
|
|
36
36
|
|
|
37
37
|
# DEPRECATED: alias for `merge_subprocesses`. Same value/behavior.
|
|
38
38
|
def enable_for_subprocesses(value = nil)
|
|
39
|
-
warn
|
|
40
|
-
|
|
39
|
+
SimpleCov::Deprecation.warn("`SimpleCov.enable_for_subprocesses` is deprecated. " \
|
|
40
|
+
"Replace with `SimpleCov.merge_subprocesses` (same value, same behavior).")
|
|
41
41
|
return @enable_for_subprocesses if defined?(@enable_for_subprocesses) && value.nil?
|
|
42
42
|
|
|
43
43
|
@enable_for_subprocesses = value || false
|
|
@@ -56,8 +56,8 @@ module SimpleCov
|
|
|
56
56
|
|
|
57
57
|
# DEPRECATED: alias for `merging`. Same value, same behavior.
|
|
58
58
|
def use_merging(use = nil)
|
|
59
|
-
warn
|
|
60
|
-
|
|
59
|
+
SimpleCov::Deprecation.warn("`SimpleCov.use_merging` is deprecated. " \
|
|
60
|
+
"Replace with `SimpleCov.merging` (same value, same behavior).")
|
|
61
61
|
@use_merging = use unless use.nil?
|
|
62
62
|
@use_merging = true unless defined?(@use_merging) && @use_merging == false
|
|
63
63
|
end
|
|
@@ -76,8 +76,8 @@ module SimpleCov
|
|
|
76
76
|
coverage = {primary_coverage => coverage} if coverage.is_a?(Numeric)
|
|
77
77
|
defaults, overrides = partition_per_file_thresholds(coverage)
|
|
78
78
|
|
|
79
|
-
warn
|
|
80
|
-
|
|
79
|
+
SimpleCov::Deprecation.warn("`SimpleCov.minimum_coverage_by_file` is deprecated. " \
|
|
80
|
+
"Replace it with:\n#{per_file_coverage_replacement(defaults, overrides)}")
|
|
81
81
|
|
|
82
82
|
raise_on_invalid_coverage(defaults, "minimum_coverage_by_file")
|
|
83
83
|
overrides.each_value { |criteria| raise_on_invalid_coverage(criteria, "minimum_coverage_by_file") }
|
|
@@ -98,8 +98,8 @@ module SimpleCov
|
|
|
98
98
|
def minimum_coverage_by_group(coverage = nil)
|
|
99
99
|
return @minimum_coverage_by_group ||= {} unless coverage
|
|
100
100
|
|
|
101
|
-
warn
|
|
102
|
-
|
|
101
|
+
SimpleCov::Deprecation.warn("`SimpleCov.minimum_coverage_by_group` is deprecated. " \
|
|
102
|
+
"Replace it with:\n#{per_group_coverage_replacement(coverage)}")
|
|
103
103
|
@minimum_coverage_by_group = coverage.dup.transform_values do |group_coverage|
|
|
104
104
|
group_coverage = {primary_coverage => group_coverage} if group_coverage.is_a?(Numeric)
|
|
105
105
|
raise_on_invalid_coverage(group_coverage, "minimum_coverage_by_group")
|
|
@@ -113,14 +113,19 @@ module SimpleCov
|
|
|
113
113
|
|
|
114
114
|
#
|
|
115
115
|
# Gets or sets the behavior to start a new forked Process.
|
|
116
|
-
# Defaults to adding " (subprocess: #{
|
|
116
|
+
# Defaults to adding " (subprocess: #{serial})" to command_name and
|
|
117
117
|
# starting SimpleCov in quiet mode.
|
|
118
118
|
#
|
|
119
119
|
def at_fork(&block)
|
|
120
120
|
@at_fork = block if block
|
|
121
|
-
@at_fork ||= lambda { |
|
|
122
|
-
#
|
|
123
|
-
|
|
121
|
+
@at_fork ||= lambda { |_pid|
|
|
122
|
+
# Needs a name that's unique per worker within a run yet identical
|
|
123
|
+
# across runs. Build it from SimpleCov's stable fork serial rather
|
|
124
|
+
# than the OS pid: with the pid, every run produced uniquely-named
|
|
125
|
+
# results that never overwrote the previous run's, so they piled up
|
|
126
|
+
# in .resultset.json until merge_timeout and the merged report's
|
|
127
|
+
# file set drifted from run to run. See issue #1171.
|
|
128
|
+
SimpleCov.command_name "#{SimpleCov.command_name} (subprocess: #{SimpleCov.subprocess_serial})"
|
|
124
129
|
# be quiet, the parent process will use the regular formatter
|
|
125
130
|
SimpleCov.print_errors false
|
|
126
131
|
SimpleCov.formatter SimpleCov::Formatter::SimpleFormatter
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "set"
|
|
4
|
+
|
|
5
|
+
module SimpleCov
|
|
6
|
+
# Emits legacy-API deprecation warnings, deduplicated by the source
|
|
7
|
+
# location that triggered them. A deprecated method called in a loop —
|
|
8
|
+
# or a config block re-evaluated once per parallel worker / spec file —
|
|
9
|
+
# otherwise repeats the same notice until stderr is unreadable. Keying
|
|
10
|
+
# on the caller location collapses those repeats to a single line while
|
|
11
|
+
# still warning separately about each distinct call site the user needs
|
|
12
|
+
# to fix. See issue #1204.
|
|
13
|
+
module Deprecation
|
|
14
|
+
module_function
|
|
15
|
+
|
|
16
|
+
# Warn about a deprecated API. `message` is the notice without the
|
|
17
|
+
# `[DEPRECATION]` tag or location prefix (both are added here).
|
|
18
|
+
#
|
|
19
|
+
# `location` defaults to the caller of the deprecated method that
|
|
20
|
+
# called us — every shipped call site is a one-level alias such as
|
|
21
|
+
# `track_files`, so the frame two up is the user code. Pass `location:`
|
|
22
|
+
# explicitly when the relevant site isn't that frame (e.g. a source
|
|
23
|
+
# file and line discovered while parsing).
|
|
24
|
+
# `Array(...)` coerces a missing backtrace (nil) to `[]` so `.first`
|
|
25
|
+
# yields nil rather than raising — and, unlike `&.`, adds no branch for
|
|
26
|
+
# the unreachable no-caller case to the project's 100% coverage target.
|
|
27
|
+
def warn(message, location: Array(Kernel.caller(2..2)).first)
|
|
28
|
+
# Key on location when we have one (collapses a deprecated call in a
|
|
29
|
+
# loop to a single warning); fall back to the message so a missing
|
|
30
|
+
# backtrace never silently swallows every notice.
|
|
31
|
+
return unless emitted.add?(location || message)
|
|
32
|
+
|
|
33
|
+
Kernel.warn "#{"#{location}: " if location}[DEPRECATION] #{message}"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Already-emitted dedup keys for this process. Parallel workers are
|
|
37
|
+
# separate processes with their own set, so each warns at most once.
|
|
38
|
+
def emitted
|
|
39
|
+
@emitted ||= Set.new
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# @api private — reset emitted state between tests.
|
|
43
|
+
def reset!
|
|
44
|
+
@emitted = Set.new
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
data/lib/simplecov/process.rb
CHANGED
|
@@ -15,8 +15,14 @@ module SimpleCov
|
|
|
15
15
|
# the child.
|
|
16
16
|
module ProcessForkHook
|
|
17
17
|
def _fork
|
|
18
|
+
active = defined?(SimpleCov) && Coverage.running?
|
|
19
|
+
# Assign the next serial in the PARENT, before the fork, so the child
|
|
20
|
+
# inherits its own stable ordinal via copy-on-write. The default
|
|
21
|
+
# at_fork uses it (instead of the child pid) to name the subprocess's
|
|
22
|
+
# result, keeping that name identical across runs. See issue #1171.
|
|
23
|
+
SimpleCov.next_subprocess_serial! if active
|
|
18
24
|
pid = super
|
|
19
|
-
SimpleCov.at_fork.call(::Process.pid) if pid.zero? &&
|
|
25
|
+
SimpleCov.at_fork.call(::Process.pid) if pid.zero? && active
|
|
20
26
|
pid
|
|
21
27
|
end
|
|
22
28
|
end
|
|
@@ -68,6 +68,14 @@ module SimpleCov
|
|
|
68
68
|
end
|
|
69
69
|
|
|
70
70
|
def warn_about_expired_results(expired_command_names)
|
|
71
|
+
# Subprocesses merge the resultset too (each forked worker calls
|
|
72
|
+
# `SimpleCov.result` to store its slice), and the default `at_fork`
|
|
73
|
+
# sets `print_errors false` for them. Without this guard the warning
|
|
74
|
+
# is emitted once per worker — N copies of the same message for an
|
|
75
|
+
# N-worker run. Gate on `print_errors` like every other SimpleCov
|
|
76
|
+
# warning so only the reporting process speaks up.
|
|
77
|
+
return unless SimpleCov.print_errors
|
|
78
|
+
|
|
71
79
|
warn "[SimpleCov]: Excluded #{expired_command_names.size} result(s) older than " \
|
|
72
80
|
"merge_timeout (#{SimpleCov.merge_timeout}s) from the merged report: " \
|
|
73
81
|
"#{expired_command_names.sort.join(', ')}. " \
|
|
@@ -123,8 +123,8 @@ module SimpleCov
|
|
|
123
123
|
|
|
124
124
|
# DEPRECATED: use `covered_percent(:branch)`.
|
|
125
125
|
def branches_coverage_percent
|
|
126
|
-
warn
|
|
127
|
-
|
|
126
|
+
SimpleCov::Deprecation.warn("`SimpleCov::SourceFile#branches_coverage_percent` is deprecated. " \
|
|
127
|
+
"Use `covered_percent(:branch)`.")
|
|
128
128
|
covered_percent(:branch)
|
|
129
129
|
end
|
|
130
130
|
|
|
@@ -176,8 +176,8 @@ module SimpleCov
|
|
|
176
176
|
|
|
177
177
|
# DEPRECATED: use `covered_percent(:method)`.
|
|
178
178
|
def methods_coverage_percent
|
|
179
|
-
warn
|
|
180
|
-
|
|
179
|
+
SimpleCov::Deprecation.warn("`SimpleCov::SourceFile#methods_coverage_percent` is deprecated. " \
|
|
180
|
+
"Use `covered_percent(:method)`.")
|
|
181
181
|
covered_percent(:method)
|
|
182
182
|
end
|
|
183
183
|
|
data/lib/simplecov/version.rb
CHANGED
data/lib/simplecov.rb
CHANGED
|
@@ -21,6 +21,22 @@ module SimpleCov
|
|
|
21
21
|
# so JSONFormatter can detect when an existing coverage.json was written
|
|
22
22
|
# by a sibling process running concurrently.
|
|
23
23
|
attr_accessor :process_start_time
|
|
24
|
+
|
|
25
|
+
# A monotonically increasing serial the parent assigns to each forked
|
|
26
|
+
# subprocess (see SimpleCov::ProcessForkHook). The default `at_fork`
|
|
27
|
+
# builds the worker's command_name from this rather than the OS pid:
|
|
28
|
+
# the serial sequence is the same from one run to the next, so a re-run
|
|
29
|
+
# overwrites the previous run's resultset entries instead of writing
|
|
30
|
+
# uniquely-named ones that pile up until merge_timeout. See issue #1171.
|
|
31
|
+
def subprocess_serial
|
|
32
|
+
@subprocess_serial ||= 0
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# @api private — bump the serial in the parent before a fork so the
|
|
36
|
+
# child inherits its own ordinal via copy-on-write.
|
|
37
|
+
def next_subprocess_serial!
|
|
38
|
+
@subprocess_serial = subprocess_serial + 1
|
|
39
|
+
end
|
|
24
40
|
# Should we take care of at_exit behavior or something else? Used by the
|
|
25
41
|
# minitest plugin. See lib/minitest/simplecov_plugin.rb.
|
|
26
42
|
attr_accessor :external_at_exit
|
|
@@ -186,6 +202,7 @@ end
|
|
|
186
202
|
require "set"
|
|
187
203
|
require "forwardable"
|
|
188
204
|
require_relative "simplecov/color"
|
|
205
|
+
require_relative "simplecov/deprecation"
|
|
189
206
|
require_relative "simplecov/configuration"
|
|
190
207
|
SimpleCov.extend SimpleCov::Configuration
|
|
191
208
|
require_relative "simplecov/coverage_statistics"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: simplecov
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.0.
|
|
4
|
+
version: 1.0.0.rc2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Erik Berlin
|
|
@@ -71,6 +71,7 @@ files:
|
|
|
71
71
|
- lib/simplecov/coverage_statistics.rb
|
|
72
72
|
- lib/simplecov/coverage_violations.rb
|
|
73
73
|
- lib/simplecov/defaults.rb
|
|
74
|
+
- lib/simplecov/deprecation.rb
|
|
74
75
|
- lib/simplecov/directive.rb
|
|
75
76
|
- lib/simplecov/exit_codes.rb
|
|
76
77
|
- lib/simplecov/exit_codes/exit_code_handling.rb
|
|
@@ -149,9 +150,9 @@ licenses:
|
|
|
149
150
|
metadata:
|
|
150
151
|
bug_tracker_uri: https://github.com/simplecov-ruby/simplecov/issues
|
|
151
152
|
changelog_uri: https://github.com/simplecov-ruby/simplecov/blob/main/CHANGELOG.md
|
|
152
|
-
documentation_uri: https://www.rubydoc.info/gems/simplecov/1.0.0.
|
|
153
|
+
documentation_uri: https://www.rubydoc.info/gems/simplecov/1.0.0.rc2
|
|
153
154
|
mailing_list_uri: https://groups.google.com/forum/#!forum/simplecov
|
|
154
|
-
source_code_uri: https://github.com/simplecov-ruby/simplecov/tree/v1.0.0.
|
|
155
|
+
source_code_uri: https://github.com/simplecov-ruby/simplecov/tree/v1.0.0.rc2
|
|
155
156
|
rubygems_mfa_required: 'true'
|
|
156
157
|
rdoc_options: []
|
|
157
158
|
require_paths:
|
|
@@ -167,7 +168,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
167
168
|
- !ruby/object:Gem::Version
|
|
168
169
|
version: '0'
|
|
169
170
|
requirements: []
|
|
170
|
-
rubygems_version: 4.0.
|
|
171
|
+
rubygems_version: 4.0.14
|
|
171
172
|
specification_version: 4
|
|
172
173
|
summary: Code coverage for Ruby
|
|
173
174
|
test_files: []
|