parallel_tests 3.8.1 → 3.10.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/Readme.md +6 -5
- data/lib/parallel_tests/cli.rb +8 -9
- data/lib/parallel_tests/cucumber/runner.rb +2 -2
- data/lib/parallel_tests/cucumber/scenarios.rb +1 -2
- data/lib/parallel_tests/gherkin/runner.rb +10 -15
- data/lib/parallel_tests/rspec/runner.rb +7 -14
- data/lib/parallel_tests/tasks.rb +60 -45
- data/lib/parallel_tests/test/runner.rb +40 -10
- data/lib/parallel_tests/version.rb +1 -1
- data/lib/parallel_tests.rb +1 -1
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 02e1b418b273cae6dc5c01e23a772e096ab58ff438b48cc6931a9f786f760edc
|
4
|
+
data.tar.gz: adbe80da32bcf51282bfb8dc7027083aaa764824ba17276e93b399b4c5444a13
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 188deeb8e49d97dce2fb367948d02531a54377528338ae3cee13e3ab5dd414b2956b1103a3dd617797761c14a933597b905942823a0ab011d49a9ea5e5b0d51a
|
7
|
+
data.tar.gz: f397c05454ab591adff4012214a2e50c37f5b562bc6824833be5ca2c6bb8280f48bab781f27304c25f952f19f5322e5afa2f7f25a2083880eba09035d81b4da3
|
data/Readme.md
CHANGED
@@ -42,7 +42,7 @@ test:
|
|
42
42
|
|
43
43
|
### Setup environment from scratch (create db and loads schema, useful for CI)
|
44
44
|
rake parallel:setup
|
45
|
-
|
45
|
+
|
46
46
|
### Drop all test databases
|
47
47
|
rake parallel:drop
|
48
48
|
|
@@ -193,15 +193,15 @@ Setup for non-rails
|
|
193
193
|
- use `ENV['TEST_ENV_NUMBER']` inside your tests to select separate db/memcache/etc. (docker compose: expose it)
|
194
194
|
|
195
195
|
- Only run a subset of files / folders:
|
196
|
-
|
196
|
+
|
197
197
|
`parallel_test test/bar test/baz/foo_text.rb`
|
198
198
|
|
199
199
|
- Pass test-options and files via `--`:
|
200
|
-
|
200
|
+
|
201
201
|
`parallel_rspec -- -t acceptance -f progress -- spec/foo_spec.rb spec/acceptance`
|
202
|
-
|
202
|
+
|
203
203
|
- Pass in test options, by using the -o flag (wrap everything in quotes):
|
204
|
-
|
204
|
+
|
205
205
|
`parallel_cucumber -n 2 -o '-p foo_profile --tags @only_this_tag or @only_that_tag --format summary'`
|
206
206
|
|
207
207
|
Options are:
|
@@ -402,6 +402,7 @@ inspired by [pivotal labs](https://blog.pivotal.io/labs/labs/parallelize-your-rs
|
|
402
402
|
- [Vikram B Kumar](https://github.com/v-kumar)
|
403
403
|
- [Joshua Pinter](https://github.com/joshuapinter)
|
404
404
|
- [Zach Dennis](https://github.com/zdennis)
|
405
|
+
- [Jon Dufresne](https://github.com/jdufresne)
|
405
406
|
|
406
407
|
[Michael Grosser](http://grosser.it)<br/>
|
407
408
|
michael@grosser.it<br/>
|
data/lib/parallel_tests/cli.rb
CHANGED
@@ -20,7 +20,7 @@ module ParallelTests
|
|
20
20
|
options[:first_is_1] ||= first_is_1?
|
21
21
|
|
22
22
|
if options[:execute]
|
23
|
-
|
23
|
+
execute_command_in_parallel(options[:execute], num_processes, options)
|
24
24
|
else
|
25
25
|
run_tests_in_parallel(num_processes, options)
|
26
26
|
end
|
@@ -100,7 +100,7 @@ module ParallelTests
|
|
100
100
|
|
101
101
|
def run_tests(group, process_number, num_processes, options)
|
102
102
|
if group.empty?
|
103
|
-
{ stdout: '', exit_status: 0, command:
|
103
|
+
{ stdout: '', exit_status: 0, command: nil, seed: nil }
|
104
104
|
else
|
105
105
|
@runner.run_tests(group, process_number, num_processes, options)
|
106
106
|
end
|
@@ -140,9 +140,8 @@ module ParallelTests
|
|
140
140
|
puts "\n\nTests have failed for a parallel_test group. Use the following command to run the group again:\n\n"
|
141
141
|
failing_sets.each do |failing_set|
|
142
142
|
command = failing_set[:command]
|
143
|
-
command = command.gsub(/;export [A-Z_]+;/, ' ') # remove ugly export statements
|
144
143
|
command = @runner.command_with_seed(command, failing_set[:seed]) if failing_set[:seed]
|
145
|
-
puts command
|
144
|
+
puts Shellwords.shelljoin(command)
|
146
145
|
end
|
147
146
|
end
|
148
147
|
end
|
@@ -238,8 +237,8 @@ module ParallelTests
|
|
238
237
|
|
239
238
|
opts.on("--only-group INT[,INT]", Array) { |groups| options[:only_group] = groups.map(&:to_i) }
|
240
239
|
|
241
|
-
opts.on("-e", "--exec [COMMAND]", "execute this code parallel and with ENV['TEST_ENV_NUMBER']") { |
|
242
|
-
opts.on("-o", "--test-options '[OPTIONS]'", "execute test commands with those options") { |arg| options[:test_options] = arg
|
240
|
+
opts.on("-e", "--exec [COMMAND]", "execute this code parallel and with ENV['TEST_ENV_NUMBER']") { |arg| options[:execute] = Shellwords.shellsplit(arg) }
|
241
|
+
opts.on("-o", "--test-options '[OPTIONS]'", "execute test commands with those options") { |arg| options[:test_options] = Shellwords.shellsplit(arg) }
|
243
242
|
opts.on("-t", "--type [TYPE]", "test(default) / rspec / cucumber / spinach") do |type|
|
244
243
|
@runner = load_runner(type)
|
245
244
|
rescue NameError, LoadError => e
|
@@ -334,8 +333,8 @@ module ParallelTests
|
|
334
333
|
new_opts = extract_test_options(argv)
|
335
334
|
return if new_opts.empty?
|
336
335
|
|
337
|
-
|
338
|
-
options[:test_options]
|
336
|
+
options[:test_options] ||= []
|
337
|
+
options[:test_options] += new_opts
|
339
338
|
end
|
340
339
|
|
341
340
|
def load_runner(type)
|
@@ -345,7 +344,7 @@ module ParallelTests
|
|
345
344
|
klass_name.split('::').inject(Object) { |x, y| x.const_get(y) }
|
346
345
|
end
|
347
346
|
|
348
|
-
def
|
347
|
+
def execute_command_in_parallel(command, num_processes, options)
|
349
348
|
runs = if options[:only_group]
|
350
349
|
options[:only_group].map { |g| g - 1 }
|
351
350
|
else
|
@@ -35,8 +35,8 @@ module ParallelTests
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def command_with_seed(cmd, seed)
|
38
|
-
clean = cmd
|
39
|
-
|
38
|
+
clean = remove_command_arguments(cmd, '--order')
|
39
|
+
[*clean, '--order', "random:#{seed}"]
|
40
40
|
end
|
41
41
|
end
|
42
42
|
end
|
@@ -4,7 +4,6 @@ require 'cucumber/runtime'
|
|
4
4
|
require 'cucumber'
|
5
5
|
require 'parallel_tests/cucumber/scenario_line_logger'
|
6
6
|
require 'parallel_tests/gherkin/listener'
|
7
|
-
require 'shellwords'
|
8
7
|
|
9
8
|
begin
|
10
9
|
gem "cuke_modeler", "~> 3.0"
|
@@ -20,7 +19,7 @@ module ParallelTests
|
|
20
19
|
def all(files, options = {})
|
21
20
|
# Parse tag expression from given test options and ignore tag pattern. Refer here to understand how new tag expression syntax works - https://github.com/cucumber/cucumber/tree/master/tag-expressions
|
22
21
|
tags = []
|
23
|
-
words = options[:test_options]
|
22
|
+
words = options[:test_options] || []
|
24
23
|
words.each_with_index { |w, i| tags << words[i + 1] if ["-t", "--tags"].include?(w) }
|
25
24
|
if ignore = options[:ignore_tag_pattern]
|
26
25
|
tags << "not (#{ignore})"
|
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
require "parallel_tests/test/runner"
|
3
|
-
require 'shellwords'
|
4
3
|
|
5
4
|
module ParallelTests
|
6
5
|
module Gherkin
|
@@ -16,17 +15,13 @@ module ParallelTests
|
|
16
15
|
end
|
17
16
|
end
|
18
17
|
|
19
|
-
sanitized_test_files = combined_scenarios.map { |val| WINDOWS ? "\"#{val}\"" : Shellwords.escape(val) }
|
20
|
-
|
21
18
|
options[:env] ||= {}
|
22
19
|
options[:env] = options[:env].merge({ 'AUTOTEST' => '1' }) if $stdout.tty?
|
23
20
|
|
24
|
-
cmd =
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
cucumber_opts(options[:test_options])
|
29
|
-
].compact.reject(&:empty?).join(' ')
|
21
|
+
cmd = executable
|
22
|
+
cmd += runtime_logging if File.directory?(File.dirname(runtime_log))
|
23
|
+
cmd += combined_scenarios
|
24
|
+
cmd += cucumber_opts(options[:test_options])
|
30
25
|
execute_command(cmd, process_number, num_processes, options)
|
31
26
|
end
|
32
27
|
|
@@ -67,17 +62,17 @@ module ParallelTests
|
|
67
62
|
end
|
68
63
|
|
69
64
|
def cucumber_opts(given)
|
70
|
-
if given
|
65
|
+
if given&.include?('--profile') || given&.include?('-p')
|
71
66
|
given
|
72
67
|
else
|
73
|
-
[given, profile_from_config]
|
68
|
+
[*given, *profile_from_config]
|
74
69
|
end
|
75
70
|
end
|
76
71
|
|
77
72
|
def profile_from_config
|
78
73
|
# copied from https://github.com/cucumber/cucumber/blob/master/lib/cucumber/cli/profile_loader.rb#L85
|
79
74
|
config = Dir.glob("{,.config/,config/}#{name}{.yml,.yaml}").first
|
80
|
-
|
75
|
+
['--profile', 'parallel'] if config && File.read(config) =~ /^parallel:/
|
81
76
|
end
|
82
77
|
|
83
78
|
def tests_in_groups(tests, num_groups, options = {})
|
@@ -91,7 +86,7 @@ module ParallelTests
|
|
91
86
|
end
|
92
87
|
|
93
88
|
def runtime_logging
|
94
|
-
|
89
|
+
['--format', 'ParallelTests::Gherkin::RuntimeLogger', '--out', runtime_log]
|
95
90
|
end
|
96
91
|
|
97
92
|
def runtime_log
|
@@ -102,11 +97,11 @@ module ParallelTests
|
|
102
97
|
if File.exist?("bin/#{name}")
|
103
98
|
ParallelTests.with_ruby_binary("bin/#{name}")
|
104
99
|
elsif ParallelTests.bundler_enabled?
|
105
|
-
"bundle exec
|
100
|
+
["bundle", "exec", name]
|
106
101
|
elsif File.file?("script/#{name}")
|
107
102
|
ParallelTests.with_ruby_binary("script/#{name}")
|
108
103
|
else
|
109
|
-
name.to_s
|
104
|
+
[name.to_s]
|
110
105
|
end
|
111
106
|
end
|
112
107
|
end
|
@@ -7,8 +7,7 @@ module ParallelTests
|
|
7
7
|
DEV_NULL = (WINDOWS ? "NUL" : "/dev/null")
|
8
8
|
class << self
|
9
9
|
def run_tests(test_files, process_number, num_processes, options)
|
10
|
-
|
11
|
-
cmd = [exe, options[:test_options], color, spec_opts, *test_files].compact.join(" ")
|
10
|
+
cmd = [*executable, *options[:test_options], *color, *spec_opts, *test_files]
|
12
11
|
execute_command(cmd, process_number, num_processes, options)
|
13
12
|
end
|
14
13
|
|
@@ -16,9 +15,9 @@ module ParallelTests
|
|
16
15
|
if File.exist?("bin/rspec")
|
17
16
|
ParallelTests.with_ruby_binary("bin/rspec")
|
18
17
|
elsif ParallelTests.bundler_enabled?
|
19
|
-
"bundle exec rspec"
|
18
|
+
["bundle", "exec", "rspec"]
|
20
19
|
else
|
21
|
-
"rspec"
|
20
|
+
["rspec"]
|
22
21
|
end
|
23
22
|
end
|
24
23
|
|
@@ -48,8 +47,8 @@ module ParallelTests
|
|
48
47
|
# --order rand:1234
|
49
48
|
# --order random:1234
|
50
49
|
def command_with_seed(cmd, seed)
|
51
|
-
clean = cmd
|
52
|
-
|
50
|
+
clean = remove_command_arguments(cmd, '--seed', '--order')
|
51
|
+
[*clean, '--seed', seed]
|
53
52
|
end
|
54
53
|
|
55
54
|
# Summarize results from threads and colorize results based on failure and pending counts.
|
@@ -71,19 +70,13 @@ module ParallelTests
|
|
71
70
|
|
72
71
|
private
|
73
72
|
|
74
|
-
# so it can be stubbed....
|
75
|
-
def run(cmd)
|
76
|
-
`#{cmd}`
|
77
|
-
end
|
78
|
-
|
79
73
|
def color
|
80
|
-
'--color --tty' if $stdout.tty?
|
74
|
+
['--color', '--tty'] if $stdout.tty?
|
81
75
|
end
|
82
76
|
|
83
77
|
def spec_opts
|
84
78
|
options_file = ['.rspec_parallel', 'spec/parallel_spec.opts', 'spec/spec.opts'].detect { |f| File.file?(f) }
|
85
|
-
|
86
|
-
"-O #{options_file}"
|
79
|
+
["-O", options_file] if options_file
|
87
80
|
end
|
88
81
|
end
|
89
82
|
end
|
data/lib/parallel_tests/tasks.rb
CHANGED
@@ -9,16 +9,8 @@ module ParallelTests
|
|
9
9
|
'test'
|
10
10
|
end
|
11
11
|
|
12
|
-
def rake_bin
|
13
|
-
# Prevent 'Exec format error' Errno::ENOEXEC on Windows
|
14
|
-
return "rake" if RUBY_PLATFORM =~ /mswin|mingw|cygwin/
|
15
|
-
binstub_path = File.join('bin', 'rake')
|
16
|
-
return binstub_path if File.exist?(binstub_path)
|
17
|
-
"rake"
|
18
|
-
end
|
19
|
-
|
20
12
|
def load_lib
|
21
|
-
$LOAD_PATH << File.expand_path(
|
13
|
+
$LOAD_PATH << File.expand_path('..', __dir__)
|
22
14
|
require "parallel_tests"
|
23
15
|
end
|
24
16
|
|
@@ -30,12 +22,15 @@ module ParallelTests
|
|
30
22
|
|
31
23
|
def run_in_parallel(cmd, options = {})
|
32
24
|
load_lib
|
33
|
-
|
25
|
+
|
34
26
|
# Using the relative path to find the binary allow to run a specific version of it
|
35
27
|
executable = File.expand_path('../../bin/parallel_test', __dir__)
|
36
|
-
|
37
|
-
command
|
38
|
-
|
28
|
+
command = ParallelTests.with_ruby_binary(executable)
|
29
|
+
command += ['--exec', Shellwords.join(cmd)]
|
30
|
+
command += ['-n', options[:count]] unless options[:count].to_s.empty?
|
31
|
+
command << '--non-parallel' if options[:non_parallel]
|
32
|
+
|
33
|
+
abort unless system(*command)
|
39
34
|
end
|
40
35
|
|
41
36
|
# this is a crazy-complex solution for a very simple problem:
|
@@ -48,16 +43,14 @@ module ParallelTests
|
|
48
43
|
# - pipefail makes pipe fail with exitstatus of first failed command
|
49
44
|
# - pipefail is not supported in (zsh)
|
50
45
|
# - defining a new rake task like silence_schema would force users to load parallel_tests in test env
|
51
|
-
# - do not use ' since run_in_parallel uses them to quote stuff
|
52
46
|
# - simple system "set -o pipefail" returns nil even though set -o pipefail exists with 0
|
53
47
|
def suppress_output(command, ignore_regex)
|
54
48
|
activate_pipefail = "set -o pipefail"
|
55
|
-
remove_ignored_lines = %{(grep -v
|
49
|
+
remove_ignored_lines = %{(grep -v #{Shellwords.escape(ignore_regex)} || true)}
|
56
50
|
|
57
|
-
if
|
58
|
-
|
59
|
-
|
60
|
-
%{/bin/bash -c '"'"'#{activate_pipefail} && (#{command}) | #{remove_ignored_lines}'"'"'}
|
51
|
+
if system('/bin/bash', '-c', "#{activate_pipefail} 2>/dev/null")
|
52
|
+
shell_command = "#{activate_pipefail} && (#{Shellwords.shelljoin(command)}) | #{remove_ignored_lines}"
|
53
|
+
['/bin/bash', '-c', shell_command]
|
61
54
|
else
|
62
55
|
command
|
63
56
|
end
|
@@ -90,7 +83,7 @@ module ParallelTests
|
|
90
83
|
options = args.shift
|
91
84
|
pass_through = args.shift
|
92
85
|
|
93
|
-
[num_processes, pattern
|
86
|
+
[num_processes, pattern, options, pass_through]
|
94
87
|
end
|
95
88
|
|
96
89
|
def schema_format_based_on_rails_version
|
@@ -125,22 +118,28 @@ end
|
|
125
118
|
namespace :parallel do
|
126
119
|
desc "Setup test databases via db:setup --> parallel:setup[num_cpus]"
|
127
120
|
task :setup, :count do |_, args|
|
128
|
-
command = "
|
121
|
+
command = [$0, "db:setup", "RAILS_ENV=#{ParallelTests::Tasks.rails_env}"]
|
129
122
|
ParallelTests::Tasks.run_in_parallel(ParallelTests::Tasks.suppress_schema_load_output(command), args)
|
130
123
|
end
|
131
124
|
|
132
125
|
desc "Create test databases via db:create --> parallel:create[num_cpus]"
|
133
126
|
task :create, :count do |_, args|
|
134
127
|
ParallelTests::Tasks.run_in_parallel(
|
135
|
-
"
|
128
|
+
[$0, "db:create", "RAILS_ENV=#{ParallelTests::Tasks.rails_env}"],
|
129
|
+
args
|
136
130
|
)
|
137
131
|
end
|
138
132
|
|
139
133
|
desc "Drop test databases via db:drop --> parallel:drop[num_cpus]"
|
140
134
|
task :drop, :count do |_, args|
|
141
135
|
ParallelTests::Tasks.run_in_parallel(
|
142
|
-
|
143
|
-
|
136
|
+
[
|
137
|
+
$0,
|
138
|
+
"db:drop",
|
139
|
+
"RAILS_ENV=#{ParallelTests::Tasks.rails_env}",
|
140
|
+
"DISABLE_DATABASE_ENVIRONMENT_CHECK=1"
|
141
|
+
],
|
142
|
+
args
|
144
143
|
)
|
145
144
|
end
|
146
145
|
|
@@ -162,7 +161,7 @@ namespace :parallel do
|
|
162
161
|
# slow: dump and load in in serial
|
163
162
|
args = args.to_hash.merge(non_parallel: true) # normal merge returns nil
|
164
163
|
task_name = Rake::Task.task_defined?('db:test:prepare') ? 'db:test:prepare' : 'app:db:test:prepare'
|
165
|
-
ParallelTests::Tasks.run_in_parallel(
|
164
|
+
ParallelTests::Tasks.run_in_parallel([$0, task_name], args)
|
166
165
|
next
|
167
166
|
end
|
168
167
|
end
|
@@ -171,23 +170,29 @@ namespace :parallel do
|
|
171
170
|
desc "Update test databases via db:migrate --> parallel:migrate[num_cpus]"
|
172
171
|
task :migrate, :count do |_, args|
|
173
172
|
ParallelTests::Tasks.run_in_parallel(
|
174
|
-
"
|
173
|
+
[$0, "db:migrate", "RAILS_ENV=#{ParallelTests::Tasks.rails_env}"],
|
174
|
+
args
|
175
175
|
)
|
176
176
|
end
|
177
177
|
|
178
178
|
desc "Rollback test databases via db:rollback --> parallel:rollback[num_cpus]"
|
179
179
|
task :rollback, :count do |_, args|
|
180
180
|
ParallelTests::Tasks.run_in_parallel(
|
181
|
-
"
|
181
|
+
[$0, "db:rollback", "RAILS_ENV=#{ParallelTests::Tasks.rails_env}"],
|
182
|
+
args
|
182
183
|
)
|
183
184
|
end
|
184
185
|
|
185
186
|
# just load the schema (good for integration server <-> no development db)
|
186
187
|
desc "Load dumped schema for test databases via db:schema:load --> parallel:load_schema[num_cpus]"
|
187
188
|
task :load_schema, :count do |_, args|
|
188
|
-
command =
|
189
|
-
|
190
|
-
|
189
|
+
command = [
|
190
|
+
$0,
|
191
|
+
ParallelTests::Tasks.purge_before_load,
|
192
|
+
"db:schema:load",
|
193
|
+
"RAILS_ENV=#{ParallelTests::Tasks.rails_env}",
|
194
|
+
"DISABLE_DATABASE_ENVIRONMENT_CHECK=1"
|
195
|
+
]
|
191
196
|
ParallelTests::Tasks.run_in_parallel(ParallelTests::Tasks.suppress_schema_load_output(command), args)
|
192
197
|
end
|
193
198
|
|
@@ -196,23 +201,34 @@ namespace :parallel do
|
|
196
201
|
desc "Load structure for test databases via db:schema:load --> parallel:load_structure[num_cpus]"
|
197
202
|
task :load_structure, :count do |_, args|
|
198
203
|
ParallelTests::Tasks.run_in_parallel(
|
199
|
-
|
200
|
-
|
204
|
+
[
|
205
|
+
$0,
|
206
|
+
ParallelTests::Tasks.purge_before_load,
|
207
|
+
"db:structure:load",
|
208
|
+
"RAILS_ENV=#{ParallelTests::Tasks.rails_env}",
|
209
|
+
"DISABLE_DATABASE_ENVIRONMENT_CHECK=1"
|
210
|
+
],
|
211
|
+
args
|
201
212
|
)
|
202
213
|
end
|
203
214
|
|
204
215
|
desc "Load the seed data from db/seeds.rb via db:seed --> parallel:seed[num_cpus]"
|
205
216
|
task :seed, :count do |_, args|
|
206
217
|
ParallelTests::Tasks.run_in_parallel(
|
207
|
-
|
218
|
+
[
|
219
|
+
$0,
|
220
|
+
"db:seed",
|
221
|
+
"RAILS_ENV=#{ParallelTests::Tasks.rails_env}"
|
222
|
+
],
|
223
|
+
args
|
208
224
|
)
|
209
225
|
end
|
210
226
|
|
211
227
|
desc "Launch given rake command in parallel"
|
212
228
|
task :rake, :command, :count do |_, args|
|
213
229
|
ParallelTests::Tasks.run_in_parallel(
|
214
|
-
"RAILS_ENV=#{ParallelTests::Tasks.rails_env}
|
215
|
-
|
230
|
+
[$0, args.command, "RAILS_ENV=#{ParallelTests::Tasks.rails_env}"],
|
231
|
+
args
|
216
232
|
)
|
217
233
|
end
|
218
234
|
|
@@ -232,16 +248,15 @@ namespace :parallel do
|
|
232
248
|
|
233
249
|
type = 'features' if test_framework == 'spinach'
|
234
250
|
# Using the relative path to find the binary allow to run a specific version of it
|
235
|
-
executable = File.
|
236
|
-
|
237
|
-
command =
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
abort unless system(command) # allow to chain tasks e.g. rake parallel:spec parallel:features
|
251
|
+
executable = File.expand_path('../../bin/parallel_test', __dir__)
|
252
|
+
|
253
|
+
command = [*ParallelTests.with_ruby_binary(executable), type, '--type', test_framework]
|
254
|
+
command += ['-n', count] if count
|
255
|
+
command += ['--pattern', pattern] if pattern
|
256
|
+
command += ['--test-options', options] if options
|
257
|
+
command << pass_through if pass_through
|
258
|
+
|
259
|
+
abort unless system(*command) # allow to chain tasks e.g. rake parallel:spec parallel:features
|
245
260
|
end
|
246
261
|
end
|
247
262
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
require 'shellwords'
|
2
3
|
require 'parallel_tests'
|
3
4
|
|
4
5
|
module ParallelTests
|
@@ -25,7 +26,14 @@ module ParallelTests
|
|
25
26
|
|
26
27
|
def run_tests(test_files, process_number, num_processes, options)
|
27
28
|
require_list = test_files.map { |file| file.gsub(" ", "\\ ") }.join(" ")
|
28
|
-
cmd =
|
29
|
+
cmd = [
|
30
|
+
*executable,
|
31
|
+
'-Itest',
|
32
|
+
'-e',
|
33
|
+
"%w[#{require_list}].each { |f| require %{./\#{f}} }",
|
34
|
+
'--',
|
35
|
+
*options[:test_options]
|
36
|
+
]
|
29
37
|
execute_command(cmd, process_number, num_processes, options)
|
30
38
|
end
|
31
39
|
|
@@ -81,17 +89,20 @@ module ParallelTests
|
|
81
89
|
"PARALLEL_TEST_GROUPS" => num_processes.to_s,
|
82
90
|
"PARALLEL_PID_FILE" => ParallelTests.pid_file_path
|
83
91
|
)
|
84
|
-
cmd = "nice
|
85
|
-
cmd = "#{cmd} 2>&1" if options[:combine_stderr]
|
92
|
+
cmd = ["nice", *cmd] if options[:nice]
|
86
93
|
|
87
|
-
puts cmd if report_process_command?(options) && !options[:serialize_stdout]
|
94
|
+
puts Shellwords.shelljoin(cmd) if report_process_command?(options) && !options[:serialize_stdout]
|
88
95
|
|
89
96
|
execute_command_and_capture_output(env, cmd, options)
|
90
97
|
end
|
91
98
|
|
92
99
|
def execute_command_and_capture_output(env, cmd, options)
|
93
100
|
pid = nil
|
94
|
-
|
101
|
+
|
102
|
+
popen_options = {}
|
103
|
+
popen_options[:err] = [:child, :out] if options[:combine_stderr]
|
104
|
+
|
105
|
+
output = IO.popen(env, cmd, popen_options) do |io|
|
95
106
|
pid = io.pid
|
96
107
|
ParallelTests.pids.add(pid)
|
97
108
|
capture_output(io, env, options)
|
@@ -100,7 +111,7 @@ module ParallelTests
|
|
100
111
|
exitstatus = $?.exitstatus
|
101
112
|
seed = output[/seed (\d+)/, 1]
|
102
113
|
|
103
|
-
output =
|
114
|
+
output = "#{Shellwords.shelljoin(cmd)}\n#{output}" if report_process_command?(options) && options[:serialize_stdout]
|
104
115
|
|
105
116
|
{ stdout: output, exit_status: exitstatus, command: cmd, seed: seed }
|
106
117
|
end
|
@@ -129,18 +140,22 @@ module ParallelTests
|
|
129
140
|
|
130
141
|
# remove old seed and add new seed
|
131
142
|
def command_with_seed(cmd, seed)
|
132
|
-
clean = cmd
|
133
|
-
|
143
|
+
clean = remove_command_arguments(cmd, '--seed')
|
144
|
+
[*clean, '--seed', seed]
|
134
145
|
end
|
135
146
|
|
136
147
|
protected
|
137
148
|
|
138
149
|
def executable
|
139
|
-
ENV
|
150
|
+
if ENV.include?('PARALLEL_TESTS_EXECUTABLE')
|
151
|
+
[ENV['PARALLEL_TESTS_EXECUTABLE']]
|
152
|
+
else
|
153
|
+
determine_executable
|
154
|
+
end
|
140
155
|
end
|
141
156
|
|
142
157
|
def determine_executable
|
143
|
-
"ruby"
|
158
|
+
["ruby"]
|
144
159
|
end
|
145
160
|
|
146
161
|
def sum_up_results(results)
|
@@ -237,6 +252,21 @@ module ParallelTests
|
|
237
252
|
Dir[File.join(folder, pattern)].uniq.sort
|
238
253
|
end
|
239
254
|
|
255
|
+
def remove_command_arguments(command, *args)
|
256
|
+
remove_next = false
|
257
|
+
command.select do |arg|
|
258
|
+
if remove_next
|
259
|
+
remove_next = false
|
260
|
+
false
|
261
|
+
elsif args.include?(arg)
|
262
|
+
remove_next = true
|
263
|
+
false
|
264
|
+
else
|
265
|
+
true
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
240
270
|
private
|
241
271
|
|
242
272
|
# fill gaps with unknown-runtime if given, average otherwise
|
data/lib/parallel_tests.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: parallel_tests
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Grosser
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-05-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: parallel
|
@@ -68,8 +68,8 @@ licenses:
|
|
68
68
|
- MIT
|
69
69
|
metadata:
|
70
70
|
bug_tracker_uri: https://github.com/grosser/parallel_tests/issues
|
71
|
-
documentation_uri: https://github.com/grosser/parallel_tests/blob/v3.
|
72
|
-
source_code_uri: https://github.com/grosser/parallel_tests/tree/v3.
|
71
|
+
documentation_uri: https://github.com/grosser/parallel_tests/blob/v3.10.0/Readme.md
|
72
|
+
source_code_uri: https://github.com/grosser/parallel_tests/tree/v3.10.0
|
73
73
|
wiki_uri: https://github.com/grosser/parallel_tests/wiki
|
74
74
|
post_install_message:
|
75
75
|
rdoc_options: []
|
@@ -86,7 +86,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
86
86
|
- !ruby/object:Gem::Version
|
87
87
|
version: '0'
|
88
88
|
requirements: []
|
89
|
-
rubygems_version: 3.3.
|
89
|
+
rubygems_version: 3.0.3.1
|
90
90
|
signing_key:
|
91
91
|
specification_version: 4
|
92
92
|
summary: Run Test::Unit / RSpec / Cucumber / Spinach in parallel
|