forking_test_runner 1.13.0 → 1.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/bin/forking-test-runner +2 -1
- data/lib/forking_test_runner/cli.rb +8 -7
- data/lib/forking_test_runner/coverage_capture.rb +3 -3
- data/lib/forking_test_runner/version.rb +2 -1
- data/lib/forking_test_runner.rb +40 -27
- metadata +88 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0a7ebca8b454c091bb661a22944f47dfe076bca28881204c35d5c5406e2edf99
|
4
|
+
data.tar.gz: 2fdc6f9e18ae663f4c6ebca965e494af978e99ed6bd38fa91527e530844a9f2b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 53998b0c82cea8ab99a6605f2a834b251d62f24c174b8dc482f917bdcc249c691a6602508e1d23b728a67a04cdd3c6c82b104fe4586dcce243f4845f9789c692
|
7
|
+
data.tar.gz: 6e507d5539e50ddf61efcc23c879270a74e7a81f28f7bf4d278b0bf19183ca2234c23ec776f0cc2ab269640b53f5bb902ac6aae186af5a1f44643bcc67f48a8d
|
data/bin/forking-test-runner
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
# enable local usage from cloned repo
|
4
|
-
root = File.expand_path(
|
5
|
+
root = File.expand_path('..', __dir__)
|
5
6
|
$LOAD_PATH << "#{root}/lib" if File.exist?("#{root}/Gemfile")
|
6
7
|
|
7
8
|
require 'forking_test_runner'
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module ForkingTestRunner
|
2
3
|
# read and delete options we support and pass the rest through to the underlying test runner (-v / --seed etc)
|
3
4
|
module CLI
|
@@ -11,9 +12,9 @@ module ForkingTestRunner
|
|
11
12
|
[
|
12
13
|
:record_runtime,
|
13
14
|
"--record-runtime=MODE",
|
14
|
-
"\n Record test runtime:\n"
|
15
|
-
|
16
|
-
|
15
|
+
"\n Record test runtime:\n " \
|
16
|
+
"simple = write to disk at --runtime-log)\n " \
|
17
|
+
"amend = write from multiple remote workers via http://github.com/grosser/amend, needs TRAVIS_REPO_SLUG & TRAVIS_BUILD_NUMBER",
|
17
18
|
String
|
18
19
|
],
|
19
20
|
[:runtime_log, "--runtime-log=FILE", "File to store runtime log in or runtime.log", String],
|
@@ -22,12 +23,12 @@ module ForkingTestRunner
|
|
22
23
|
[:groups, "--groups=NUM", "How many groups there are in total (use with --group)", Integer],
|
23
24
|
[:version, "--version", "Show version"],
|
24
25
|
[:help, "--help", "Show help"]
|
25
|
-
]
|
26
|
+
].freeze
|
26
27
|
|
27
28
|
class << self
|
28
29
|
def parse_options(argv)
|
29
30
|
options = OPTIONS.each_with_object({}) do |(setting, flag, _, type), all|
|
30
|
-
all[setting] = delete_argv(flag.split('=', 2)[0], argv, type:
|
31
|
+
all[setting] = delete_argv(flag.split('=', 2)[0], argv, type:)
|
31
32
|
end
|
32
33
|
|
33
34
|
# show version
|
@@ -43,8 +44,8 @@ module ForkingTestRunner
|
|
43
44
|
end
|
44
45
|
|
45
46
|
# check if we can use merge_coverage
|
46
|
-
if options.fetch(:merge_coverage)
|
47
|
-
abort "merge_coverage does not work on ruby prior to 2.3"
|
47
|
+
if options.fetch(:merge_coverage) && "2.3.0" > RUBY_VERSION
|
48
|
+
abort "merge_coverage does not work on ruby prior to 2.3"
|
48
49
|
end
|
49
50
|
|
50
51
|
if !!options.fetch(:group) ^ !!options.fetch(:groups)
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module ForkingTestRunner
|
2
3
|
module CoverageCapture
|
3
4
|
# override Coverage.result to add pre-fork captured coverage
|
@@ -7,8 +8,7 @@ module ForkingTestRunner
|
|
7
8
|
end
|
8
9
|
|
9
10
|
# deprecated, single_cov checks for this, so leave it here
|
10
|
-
def capture_coverage
|
11
|
-
end
|
11
|
+
def capture_coverage!; end
|
12
12
|
|
13
13
|
class << self
|
14
14
|
attr_accessor :coverage
|
@@ -49,7 +49,7 @@ module ForkingTestRunner
|
|
49
49
|
def merge_lines_coverage(a, b)
|
50
50
|
b.each_with_index.map do |b_count, i|
|
51
51
|
a_count = a[i]
|
52
|
-
|
52
|
+
a_count.nil? && b_count.nil? ? nil : a_count.to_i + b_count.to_i
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
data/lib/forking_test_runner.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'benchmark'
|
2
3
|
require 'optparse'
|
3
4
|
require 'forking_test_runner/version'
|
@@ -8,10 +9,9 @@ require 'tempfile'
|
|
8
9
|
|
9
10
|
module ForkingTestRunner
|
10
11
|
CLEAR = "------"
|
11
|
-
|
12
|
+
COVERAGE_REPORT_PREFIX = "coverage/fork-"
|
12
13
|
|
13
14
|
class << self
|
14
|
-
|
15
15
|
attr_accessor :before_fork_callbacks, :after_fork_callbacks
|
16
16
|
|
17
17
|
def cli(argv)
|
@@ -42,19 +42,19 @@ module ForkingTestRunner
|
|
42
42
|
|
43
43
|
# run all the tests
|
44
44
|
results = with_lock do |lock|
|
45
|
-
Parallel.map_with_index(test_groups, in_processes: parallel || 0) do |
|
45
|
+
Parallel.map_with_index(test_groups, in_processes: parallel || 0) do |tests_group, env_index|
|
46
46
|
if parallel
|
47
47
|
ENV["TEST_ENV_NUMBER"] = (env_index == 0 ? '' : (env_index + 1).to_s) # NOTE: does not support first_is_1 option
|
48
48
|
end
|
49
49
|
|
50
50
|
reraise_clean_ar_error { load_test_env }
|
51
51
|
|
52
|
-
|
52
|
+
tests_group.map do |file, expected|
|
53
53
|
print_started file unless parallel
|
54
54
|
result = [file, expected, *benchmark { run_test(file) }]
|
55
55
|
sync_stdout lock do
|
56
56
|
print_started file if parallel
|
57
|
-
print_finished
|
57
|
+
print_finished(*result)
|
58
58
|
end
|
59
59
|
result
|
60
60
|
end
|
@@ -64,9 +64,11 @@ module ForkingTestRunner
|
|
64
64
|
unless @options.fetch(:quiet)
|
65
65
|
# pretty print the results
|
66
66
|
puts "\nResults:"
|
67
|
-
puts
|
68
|
-
|
69
|
-
|
67
|
+
puts(
|
68
|
+
results
|
69
|
+
.sort_by { |_, _, _, r, _| r ? 0 : 1 } # failures should be last so they are easy to find
|
70
|
+
.map { |f, _, _, r, _| "#{f}: #{r ? "OK" : "Fail"}" }
|
71
|
+
)
|
70
72
|
puts
|
71
73
|
end
|
72
74
|
|
@@ -94,9 +96,9 @@ module ForkingTestRunner
|
|
94
96
|
|
95
97
|
private
|
96
98
|
|
97
|
-
def with_lock(&
|
99
|
+
def with_lock(&)
|
98
100
|
return yield unless @options.fetch(:parallel)
|
99
|
-
Tempfile.open"forking-test-runner-lock", &
|
101
|
+
Tempfile.open("forking-test-runner-lock", &)
|
100
102
|
end
|
101
103
|
|
102
104
|
def sync_stdout(lock)
|
@@ -161,7 +163,7 @@ module ForkingTestRunner
|
|
161
163
|
File.write(log, data)
|
162
164
|
when 'amend'
|
163
165
|
if id = ENV["BUILDKITE_JOB_ID"]
|
164
|
-
slug = ENV.fetch("BUILDKITE_ORG_SLUG")
|
166
|
+
slug = "#{ENV.fetch("BUILDKITE_ORG_SLUG")}-#{ENV.fetch("BUILDKITE_PIPELINE_SLUG")}"
|
165
167
|
else
|
166
168
|
slug = ENV.fetch("TRAVIS_REPO_SLUG").sub("/", "-")
|
167
169
|
id = ENV.fetch("TRAVIS_BUILD_NUMBER")
|
@@ -212,7 +214,7 @@ module ForkingTestRunner
|
|
212
214
|
e = begin
|
213
215
|
yield
|
214
216
|
nil
|
215
|
-
rescue
|
217
|
+
rescue StandardError
|
216
218
|
$!
|
217
219
|
end
|
218
220
|
|
@@ -223,7 +225,7 @@ module ForkingTestRunner
|
|
223
225
|
def load_test_helper
|
224
226
|
disable_test_autorun
|
225
227
|
require 'rspec/core' if @options.fetch(:rspec)
|
226
|
-
helper =
|
228
|
+
helper = @options.fetch(:helper) || (@options.fetch(:rspec) ? "spec/spec_helper" : "test/test_helper")
|
227
229
|
require "./#{helper}"
|
228
230
|
end
|
229
231
|
|
@@ -235,14 +237,21 @@ module ForkingTestRunner
|
|
235
237
|
# reuse our pre-loaded fixtures even if we have a different connection
|
236
238
|
fixtures = ActiveRecord::FixtureSet
|
237
239
|
fixtures_eigenclass = class << fixtures; self; end
|
238
|
-
|
240
|
+
|
241
|
+
name = (ActiveRecord::VERSION::STRING >= "7.2.0" ? :cache_for_connection_pool : :cache_for_connection)
|
242
|
+
fixtures_eigenclass.send(:define_method, name) do |_pool|
|
239
243
|
fixtures.class_variable_get(:@@all_cached_fixtures)[:unique]
|
240
244
|
end
|
241
245
|
|
242
246
|
ActiveSupport::TestCase.fixtures :all
|
243
247
|
|
244
248
|
fixtures.create_fixtures(
|
245
|
-
ActiveSupport::TestCase.
|
249
|
+
(if ActiveSupport::TestCase.respond_to?(:fixture_paths)
|
250
|
+
ActiveSupport::TestCase.fixture_paths
|
251
|
+
else
|
252
|
+
ActiveSupport::TestCase.fixture_path
|
253
|
+
end
|
254
|
+
), # TODO: remove after dropping rails 7,0 support
|
246
255
|
ActiveSupport::TestCase.fixture_table_names,
|
247
256
|
ActiveSupport::TestCase.fixture_class_names
|
248
257
|
)
|
@@ -268,7 +277,7 @@ module ForkingTestRunner
|
|
268
277
|
|
269
278
|
wpipe.close
|
270
279
|
|
271
|
-
buffer = ""
|
280
|
+
buffer = +""
|
272
281
|
|
273
282
|
while ch = rpipe.read(1)
|
274
283
|
buffer << ch
|
@@ -283,7 +292,11 @@ module ForkingTestRunner
|
|
283
292
|
def preserve_tty
|
284
293
|
was_tty = $stdout.tty?
|
285
294
|
yield
|
286
|
-
|
295
|
+
if was_tty
|
296
|
+
def $stdout.tty?;
|
297
|
+
true;
|
298
|
+
end
|
299
|
+
end
|
287
300
|
end
|
288
301
|
|
289
302
|
def run_test(file)
|
@@ -294,14 +307,13 @@ module ForkingTestRunner
|
|
294
307
|
SimpleCov.command_name file
|
295
308
|
end
|
296
309
|
if partial_reports_for_single_cov?
|
297
|
-
SingleCov.coverage_report = "#{
|
310
|
+
SingleCov.coverage_report = "#{COVERAGE_REPORT_PREFIX}#{Process.pid}.json"
|
298
311
|
end
|
299
312
|
|
300
313
|
@after_fork_callbacks.each(&:call)
|
301
314
|
|
302
315
|
if active_record?
|
303
|
-
|
304
|
-
ActiveRecord::Base.establish_connection key
|
316
|
+
ActiveRecord::Base.establish_connection :test
|
305
317
|
end
|
306
318
|
enable_test_autorun(file)
|
307
319
|
end
|
@@ -317,7 +329,8 @@ module ForkingTestRunner
|
|
317
329
|
def change_program_name_to(name)
|
318
330
|
return yield if @options.fetch(:parallel)
|
319
331
|
begin
|
320
|
-
old
|
332
|
+
old = $0
|
333
|
+
$0 = name
|
321
334
|
yield
|
322
335
|
ensure
|
323
336
|
$0 = old
|
@@ -331,14 +344,14 @@ module ForkingTestRunner
|
|
331
344
|
tests = ParallelTests::Test::Runner.send(
|
332
345
|
:tests_with_size,
|
333
346
|
tests,
|
334
|
-
runtime_log
|
335
|
-
group_by:
|
347
|
+
runtime_log:,
|
348
|
+
group_by:
|
336
349
|
)
|
337
350
|
groups = ParallelTests::Grouper.in_even_groups_by_size(tests, group_count, {})
|
338
351
|
group = groups[group - 1] || raise("Group #{group} not found")
|
339
352
|
|
340
353
|
# return tests with runtime
|
341
|
-
tests =
|
354
|
+
tests = tests.to_h
|
342
355
|
group.map { |test| [test, (tests[test] if group_by == :runtime)] }
|
343
356
|
end
|
344
357
|
|
@@ -354,7 +367,7 @@ module ForkingTestRunner
|
|
354
367
|
end
|
355
368
|
end
|
356
369
|
|
357
|
-
def toggle_test_autorun(value, file=nil)
|
370
|
+
def toggle_test_autorun(value, file = nil)
|
358
371
|
if @options.fetch(:rspec)
|
359
372
|
if value
|
360
373
|
exit(RSpec::Core::Runner.run([file] + ARGV))
|
@@ -376,7 +389,7 @@ module ForkingTestRunner
|
|
376
389
|
end
|
377
390
|
|
378
391
|
def summarize_partial_reports
|
379
|
-
reports = Dir.glob("#{
|
392
|
+
reports = Dir.glob("#{COVERAGE_REPORT_PREFIX}*")
|
380
393
|
return if reports.empty?
|
381
394
|
key = nil
|
382
395
|
|
@@ -391,7 +404,7 @@ module ForkingTestRunner
|
|
391
404
|
File.unlink(report) # do not leave junk behind
|
392
405
|
end
|
393
406
|
|
394
|
-
data = JSON.pretty_generate(key => {"coverage" => coverage, "timestamp" => Time.now.to_i })
|
407
|
+
data = JSON.pretty_generate(key => { "coverage" => coverage, "timestamp" => Time.now.to_i })
|
395
408
|
File.write(SingleCov.coverage_report, data)
|
396
409
|
|
397
410
|
# make it not override our report when it finishes for main process
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: forking_test_runner
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.15.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Grosser
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-09-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: parallel_tests
|
@@ -39,7 +39,27 @@ dependencies:
|
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '2.4'
|
48
|
+
- - ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: 2.4.22
|
51
|
+
type: :development
|
52
|
+
prerelease: false
|
53
|
+
version_requirements: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - "~>"
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: '2.4'
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: 2.4.22
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: drb
|
43
63
|
requirement: !ruby/object:Gem::Requirement
|
44
64
|
requirements:
|
45
65
|
- - ">="
|
@@ -53,7 +73,7 @@ dependencies:
|
|
53
73
|
- !ruby/object:Gem::Version
|
54
74
|
version: '0'
|
55
75
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
76
|
+
name: logger
|
57
77
|
requirement: !ruby/object:Gem::Requirement
|
58
78
|
requirements:
|
59
79
|
- - ">="
|
@@ -67,7 +87,7 @@ dependencies:
|
|
67
87
|
- !ruby/object:Gem::Version
|
68
88
|
version: '0'
|
69
89
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
90
|
+
name: minitest
|
71
91
|
requirement: !ruby/object:Gem::Requirement
|
72
92
|
requirements:
|
73
93
|
- - ">="
|
@@ -81,7 +101,21 @@ dependencies:
|
|
81
101
|
- !ruby/object:Gem::Version
|
82
102
|
version: '0'
|
83
103
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
104
|
+
name: mutex_m
|
105
|
+
requirement: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - ">="
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
type: :development
|
111
|
+
prerelease: false
|
112
|
+
version_requirements: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - ">="
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '0'
|
117
|
+
- !ruby/object:Gem::Dependency
|
118
|
+
name: rake
|
85
119
|
requirement: !ruby/object:Gem::Requirement
|
86
120
|
requirements:
|
87
121
|
- - ">="
|
@@ -94,7 +128,49 @@ dependencies:
|
|
94
128
|
- - ">="
|
95
129
|
- !ruby/object:Gem::Version
|
96
130
|
version: '0'
|
97
|
-
|
131
|
+
- !ruby/object:Gem::Dependency
|
132
|
+
name: rspec
|
133
|
+
requirement: !ruby/object:Gem::Requirement
|
134
|
+
requirements:
|
135
|
+
- - ">="
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: '0'
|
138
|
+
type: :development
|
139
|
+
prerelease: false
|
140
|
+
version_requirements: !ruby/object:Gem::Requirement
|
141
|
+
requirements:
|
142
|
+
- - ">="
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: '0'
|
145
|
+
- !ruby/object:Gem::Dependency
|
146
|
+
name: rubocop
|
147
|
+
requirement: !ruby/object:Gem::Requirement
|
148
|
+
requirements:
|
149
|
+
- - "~>"
|
150
|
+
- !ruby/object:Gem::Version
|
151
|
+
version: 1.66.1
|
152
|
+
type: :development
|
153
|
+
prerelease: false
|
154
|
+
version_requirements: !ruby/object:Gem::Requirement
|
155
|
+
requirements:
|
156
|
+
- - "~>"
|
157
|
+
- !ruby/object:Gem::Version
|
158
|
+
version: 1.66.1
|
159
|
+
- !ruby/object:Gem::Dependency
|
160
|
+
name: sqlite3
|
161
|
+
requirement: !ruby/object:Gem::Requirement
|
162
|
+
requirements:
|
163
|
+
- - "~>"
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: '1.4'
|
166
|
+
type: :development
|
167
|
+
prerelease: false
|
168
|
+
version_requirements: !ruby/object:Gem::Requirement
|
169
|
+
requirements:
|
170
|
+
- - "~>"
|
171
|
+
- !ruby/object:Gem::Version
|
172
|
+
version: '1.4'
|
173
|
+
description:
|
98
174
|
email: michael@grosser.it
|
99
175
|
executables:
|
100
176
|
- forking-test-runner
|
@@ -111,7 +187,7 @@ homepage: https://github.com/grosser/forking_test_runner
|
|
111
187
|
licenses:
|
112
188
|
- MIT
|
113
189
|
metadata: {}
|
114
|
-
post_install_message:
|
190
|
+
post_install_message:
|
115
191
|
rdoc_options: []
|
116
192
|
require_paths:
|
117
193
|
- lib
|
@@ -119,15 +195,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
119
195
|
requirements:
|
120
196
|
- - ">="
|
121
197
|
- !ruby/object:Gem::Version
|
122
|
-
version:
|
198
|
+
version: 3.1.0
|
123
199
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
124
200
|
requirements:
|
125
201
|
- - ">="
|
126
202
|
- !ruby/object:Gem::Version
|
127
203
|
version: '0'
|
128
204
|
requirements: []
|
129
|
-
rubygems_version: 3.
|
130
|
-
signing_key:
|
205
|
+
rubygems_version: 3.4.10
|
206
|
+
signing_key:
|
131
207
|
specification_version: 4
|
132
208
|
summary: Run every test in a fork to avoid pollution and get clean output per test
|
133
209
|
test_files: []
|