parallel_tests 4.4.0 → 4.7.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cf9a4f09819ff1193b0f02d9148f72d7b12e4c2efc2ca4e5e7981eb6959ebfef
4
- data.tar.gz: f86bdeb95cb93b8d8d79a81727e719014a481c18520da973480ff44d6828ffdb
3
+ metadata.gz: b091de564b1cd9f2c57b94dd973bceea01f7722e4c6bafbe71e6b75c7a265421
4
+ data.tar.gz: bf14a02a03bef8046e2973a904701f03b10bdae1ef8a84654511c18631efe179
5
5
  SHA512:
6
- metadata.gz: 549401be10742522594fbd9f9ba1eb657c7689c13be3f9034bb7ee78225a7b86cf127b83d1f16cac932b639cfec92ecac9644e8aff9aa488b39e3980eb23ff6c
7
- data.tar.gz: ad909f442e744a869bc4db59b9bf2bc9b3559e888f2d017cee58fa51b4d8563f5dc9123d6ce48317fe65f56e7d6f4f4d89c56274960d14ec1befbe5e3cabcc2d
6
+ metadata.gz: d4d7df8aed6d01ba8a9b98064a4c88ad7b88270884d9b5f24c34c2094772974c81fef357c9534e97265e57603b780c9b61af4b1a70a32ae6891ba87256633dfd
7
+ data.tar.gz: a0f0e19e7d02d3046f41ebe8c51a72056bd840d25b54947564b5b015df8946f0e4b0c86920b3cabca7ff1a82f29dcbb44e53daeaf92ae3721de29b6388c92fe0
data/Readme.md CHANGED
@@ -33,35 +33,45 @@ test:
33
33
  ### Create additional database(s)
34
34
  rake parallel:create
35
35
 
36
+ ### (Multi-DB) Create individual database
37
+ rake parallel:create:<database>
38
+ rake parallel:create:secondary
39
+
36
40
  ### Copy development schema (repeat after migrations)
37
41
  rake parallel:prepare
38
42
 
39
43
  ### Run migrations in additional database(s) (repeat after migrations)
40
44
  rake parallel:migrate
41
45
 
46
+ ### (Multi-DB) Run migrations in individual database
47
+ rake parallel:migrate:<database>
48
+
42
49
  ### Setup environment from scratch (create db and loads schema, useful for CI)
43
50
  rake parallel:setup
44
51
 
45
52
  ### Drop all test databases
46
53
  rake parallel:drop
47
54
 
55
+ ### (Multi-DB) Drop individual test database
56
+ rake parallel:drop:<database>
57
+
48
58
  ### Run!
49
59
  rake parallel:test # Minitest
50
60
  rake parallel:spec # RSpec
51
61
  rake parallel:features # Cucumber
52
62
  rake parallel:features-spinach # Spinach
53
63
 
54
- rake parallel:test[1] --> force 1 CPU --> 86 seconds
64
+ rake "parallel:test[1]" --> force 1 CPU --> 86 seconds
55
65
  rake parallel:test --> got 2 CPUs? --> 47 seconds
56
66
  rake parallel:test --> got 4 CPUs? --> 26 seconds
57
67
  ...
58
68
 
59
69
  Test by pattern with Regex (e.g. use one integration server per subfolder / see if you broke any 'user'-related tests)
60
70
 
61
- rake parallel:test[^test/unit] # every test file in test/unit folder
62
- rake parallel:test[user] # run users_controller + user_helper + user tests
63
- rake parallel:test['user|product'] # run user and product related tests
64
- rake parallel:spec['spec\/(?!features)'] # run RSpec tests except the tests in spec/features
71
+ rake "parallel:test[^test/unit]" # every test file in test/unit folder
72
+ rake "parallel:test[user]" # run users_controller + user_helper + user tests
73
+ rake "parallel:test['user|product']" # run user and product related tests
74
+ rake "parallel:spec['spec\/(?!features)']" # run RSpec tests except the tests in spec/features
65
75
 
66
76
 
67
77
  ### Example output
@@ -77,9 +87,9 @@ Test by pattern with Regex (e.g. use one integration server per subfolder / see
77
87
  ```Bash
78
88
  RAILS_ENV=test parallel_test -e "rake my:custom:task"
79
89
  # or
80
- rake parallel:rake[my:custom:task]
90
+ rake "parallel:rake[my:custom:task]"
81
91
  # limited parallelism
82
- rake parallel:rake[my:custom:task,2]
92
+ rake "parallel:rake[my:custom:task,2]"
83
93
  ```
84
94
 
85
95
 
@@ -240,8 +250,9 @@ Options are:
240
250
  -m, --multiply-processes [FLOAT] use given number as a multiplier of processes to run
241
251
  -s, --single [PATTERN] Run all matching files in the same process
242
252
  -i, --isolate Do not run any other tests in the group used by --single(-s)
243
- --isolate-n [PROCESSES] Use 'isolate' singles with number of processes, default: 1.
253
+ --isolate-n [PROCESSES] Use 'isolate' singles with number of processes, default: 1
244
254
  --highest-exit-status Exit with the highest exit status provided by test run(s)
255
+ --failure-exit-code [INT] Specify the exit code to use when tests fail
245
256
  --specify-groups [SPECS] Use 'specify-groups' if you want to specify multiple specs running in multiple
246
257
  processes in a specific formation. Commas indicate specs in the same process,
247
258
  pipes indicate specs in a new process. Cannot use with --single, --isolate, or
@@ -250,9 +261,8 @@ Options are:
250
261
  Process 1 will contain 1_spec.rb and 2_spec.rb
251
262
  Process 2 will contain 3_spec.rb
252
263
  Process 3 will contain all other specs
253
- --only-group INT[,INT] Only run the given group numbers. Note that this will force the 'filesize'
254
- grouping strategy (even when the runtime log is present) unless you explicitly
255
- set it otherwise via the '-group-by' flag.
264
+ --only-group INT[,INT] Only run the given group numbers.
265
+ Changes `--group-by` default to 'filesize'.
256
266
  -e, --exec [COMMAND] execute this code parallel and with ENV['TEST_ENV_NUMBER']
257
267
  -o, --test-options '[OPTIONS]' execute test commands with those options
258
268
  -t, --type [TYPE] test(default) / rspec / cucumber / spinach
@@ -269,11 +279,14 @@ Options are:
269
279
  --nice execute test commands with low priority.
270
280
  --runtime-log [PATH] Location of previously recorded test runtimes
271
281
  --allowed-missing [INT] Allowed percentage of missing runtimes (default = 50)
282
+ --allow-duplicates When detecting files to run, allow duplicates
272
283
  --unknown-runtime [FLOAT] Use given number as unknown runtime (otherwise use average time)
273
284
  --first-is-1 Use "1" as TEST_ENV_NUMBER to not reuse the default test environment
274
285
  --fail-fast Stop all groups when one group fails (best used with --test-options '--fail-fast' if supported
275
286
  --verbose Print debug output
276
- --verbose-command Displays the command that will be executed by each process and when there are failures displays the command executed by each process that failed
287
+ --verbose-command Combines options --verbose-process-command and --verbose-rerun-command
288
+ --verbose-process-command Print the command that will be executed by each process before it begins
289
+ --verbose-rerun-command After a process fails, print the command executed by that process
277
290
  --quiet Print only tests output
278
291
  -v, --version Show Version
279
292
  -h, --help Show this.
@@ -427,6 +440,9 @@ inspired by [pivotal labs](https://blog.pivotal.io/labs/labs/parallelize-your-rs
427
440
  - [Jon Dufresne](https://github.com/jdufresne)
428
441
  - [Eric Kessler](https://github.com/enkessler)
429
442
  - [Adis Osmonov](https://github.com/adis-io)
443
+ - [Josh Westbrook](https://github.com/joshwestbrook)
444
+ - [Jay Dorsey](https://github.com/jaydorsey)
445
+ - [hatsu](https://github.com/hatsu38)
430
446
 
431
447
  [Michael Grosser](http://grosser.it)<br/>
432
448
  michael@grosser.it<br/>
@@ -57,8 +57,8 @@ module ParallelTests
57
57
  Tempfile.open 'parallel_tests-lock' do |lock|
58
58
  ParallelTests.with_pid_file do
59
59
  simulate_output_for_ci options[:serialize_stdout] do
60
- Parallel.map(items, in_threads: num_processes) do |item|
61
- result = yield(item)
60
+ Parallel.map_with_index(items, in_threads: num_processes) do |item, index|
61
+ result = yield(item, index)
62
62
  reprint_output(result, lock.path) if options[:serialize_stdout]
63
63
  ParallelTests.stop_all_processes if options[:fail_fast] && result[:exit_status] != 0
64
64
  result
@@ -81,8 +81,8 @@ module ParallelTests
81
81
  end
82
82
 
83
83
  report_number_of_tests(groups) unless options[:quiet]
84
- test_results = execute_in_parallel(groups, groups.size, options) do |group|
85
- run_tests(group, groups.index(group), num_processes, options)
84
+ test_results = execute_in_parallel(groups, groups.size, options) do |group, index|
85
+ run_tests(group, index, num_processes, options)
86
86
  end
87
87
  report_results(test_results, options) unless options[:quiet]
88
88
  end
@@ -96,8 +96,9 @@ module ParallelTests
96
96
  if any_test_failed?(test_results)
97
97
  warn final_fail_message
98
98
 
99
- # return the highest exit status to allow sub-processes to send things other than 1
100
- exit_status = if options[:highest_exit_status]
99
+ exit_status = if options[:failure_exit_code]
100
+ options[:failure_exit_code]
101
+ elsif options[:highest_exit_status]
101
102
  test_results.map { |data| data.fetch(:exit_status) }.max
102
103
  else
103
104
  1
@@ -145,7 +146,7 @@ module ParallelTests
145
146
  failing_sets = test_results.reject { |r| r[:exit_status] == 0 }
146
147
  return if failing_sets.none?
147
148
 
148
- if options[:verbose] || options[:verbose_command]
149
+ if options[:verbose] || options[:verbose_rerun_command]
149
150
  puts "\n\nTests have failed for a parallel_test group. Use the following command to run the group again:\n\n"
150
151
  failing_sets.each do |failing_set|
151
152
  command = failing_set[:command]
@@ -223,12 +224,19 @@ module ParallelTests
223
224
  opts.on(
224
225
  "--isolate-n [PROCESSES]",
225
226
  Integer,
226
- "Use 'isolate' singles with number of processes, default: 1."
227
+ "Use 'isolate' singles with number of processes, default: 1"
227
228
  ) { |n| options[:isolate_count] = n }
228
229
 
229
- opts.on("--highest-exit-status", "Exit with the highest exit status provided by test run(s)") do
230
- options[:highest_exit_status] = true
231
- end
230
+ opts.on(
231
+ "--highest-exit-status",
232
+ "Exit with the highest exit status provided by test run(s)"
233
+ ) { options[:highest_exit_status] = true }
234
+
235
+ opts.on(
236
+ "--failure-exit-code [INT]",
237
+ Integer,
238
+ "Specify the exit code to use when tests fail"
239
+ ) { |code| options[:failure_exit_code] = code }
232
240
 
233
241
  opts.on(
234
242
  "--specify-groups [SPECS]",
@@ -237,7 +245,7 @@ module ParallelTests
237
245
  processes in a specific formation. Commas indicate specs in the same process,
238
246
  pipes indicate specs in a new process. Cannot use with --single, --isolate, or
239
247
  --isolate-n. Ex.
240
- $ parallel_test -n 3 . --specify-groups '1_spec.rb,2_spec.rb|3_spec.rb'
248
+ $ parallel_tests -n 3 . --specify-groups '1_spec.rb,2_spec.rb|3_spec.rb'
241
249
  Process 1 will contain 1_spec.rb and 2_spec.rb
242
250
  Process 2 will contain 3_spec.rb
243
251
  Process 3 will contain all other specs
@@ -278,11 +286,14 @@ module ParallelTests
278
286
  opts.on("--nice", "execute test commands with low priority.") { options[:nice] = true }
279
287
  opts.on("--runtime-log [PATH]", "Location of previously recorded test runtimes") { |path| options[:runtime_log] = path }
280
288
  opts.on("--allowed-missing [INT]", Integer, "Allowed percentage of missing runtimes (default = 50)") { |percent| options[:allowed_missing_percent] = percent }
289
+ opts.on('--allow-duplicates', 'When detecting files to run, allow duplicates') { options[:allow_duplicates] = true }
281
290
  opts.on("--unknown-runtime [FLOAT]", Float, "Use given number as unknown runtime (otherwise use average time)") { |time| options[:unknown_runtime] = time }
282
291
  opts.on("--first-is-1", "Use \"1\" as TEST_ENV_NUMBER to not reuse the default test environment") { options[:first_is_1] = true }
283
292
  opts.on("--fail-fast", "Stop all groups when one group fails (best used with --test-options '--fail-fast' if supported") { options[:fail_fast] = true }
284
293
  opts.on("--verbose", "Print debug output") { options[:verbose] = true }
285
- opts.on("--verbose-command", "Displays the command that will be executed by each process and when there are failures displays the command executed by each process that failed") { options[:verbose_command] = true }
294
+ opts.on("--verbose-command", "Combines options --verbose-process-command and --verbose-rerun-command") { options.merge! verbose_process_command: true, verbose_rerun_command: true }
295
+ opts.on("--verbose-process-command", "Print the command that will be executed by each process before it begins") { options[:verbose_process_command] = true }
296
+ opts.on("--verbose-rerun-command", "After a process fails, print the command executed by that process") { options[:verbose_rerun_command] = true }
286
297
  opts.on("--quiet", "Print only tests output") { options[:quiet] = true }
287
298
  opts.on("-v", "--version", "Show Version") do
288
299
  puts ParallelTests::VERSION
@@ -330,6 +341,10 @@ module ParallelTests
330
341
  raise "Can't pass --specify-groups with any of these keys: --single, --isolate, or --isolate-n"
331
342
  end
332
343
 
344
+ if options[:failure_exit_code] && options[:highest_exit_status]
345
+ raise "Can't pass --failure-exit-code and --highest-exit-status"
346
+ end
347
+
333
348
  options
334
349
  end
335
350
 
@@ -15,7 +15,7 @@ module ParallelTests
15
15
 
16
16
  def runtime_logging
17
17
  # Not Yet Supported
18
- ""
18
+ []
19
19
  end
20
20
  end
21
21
  end
@@ -48,6 +48,9 @@ module ParallelTests
48
48
  activate_pipefail = "set -o pipefail"
49
49
  remove_ignored_lines = %{(grep -v #{Shellwords.escape(ignore_regex)} || true)}
50
50
 
51
+ # remove nil values (ex: #purge_before_load returns nil)
52
+ command.compact!
53
+
51
54
  if system('/bin/bash', '-c', "#{activate_pipefail} 2>/dev/null")
52
55
  shell_command = "#{activate_pipefail} && (#{Shellwords.shelljoin(command)}) | #{remove_ignored_lines}"
53
56
  ['/bin/bash', '-c', shell_command]
@@ -125,6 +128,24 @@ module ParallelTests
125
128
  command
126
129
  end
127
130
 
131
+ def configured_databases
132
+ return [] unless defined?(ActiveRecord) && rails_61_or_greater?
133
+
134
+ @@configured_databases ||= ActiveRecord::Tasks::DatabaseTasks.setup_initial_database_yaml
135
+ end
136
+
137
+ def for_each_database(&block)
138
+ # Use nil to represent all databases
139
+ block&.call(nil)
140
+
141
+ # skip if not rails or old rails version
142
+ return if !defined?(ActiveRecord::Tasks::DatabaseTasks) || !ActiveRecord::Tasks::DatabaseTasks.respond_to?(:for_each)
143
+
144
+ ActiveRecord::Tasks::DatabaseTasks.for_each(configured_databases) do |name|
145
+ block&.call(name)
146
+ end
147
+ end
148
+
128
149
  private
129
150
 
130
151
  def rails_7_or_greater?
@@ -145,25 +166,33 @@ namespace :parallel do
145
166
  ParallelTests::Tasks.run_in_parallel(ParallelTests::Tasks.suppress_schema_load_output(command), args)
146
167
  end
147
168
 
148
- desc "Create test databases via db:create --> parallel:create[num_cpus]"
149
- task :create, :count do |_, args|
150
- ParallelTests::Tasks.run_in_parallel(
151
- [$0, "db:create", "RAILS_ENV=#{ParallelTests::Tasks.rails_env}"],
152
- args
153
- )
169
+ ParallelTests::Tasks.for_each_database do |name|
170
+ task_name = 'create'
171
+ task_name += ":#{name}" if name
172
+ desc "Create test#{" #{name}" if name} database via db:#{task_name} --> parallel:#{task_name}[num_cpus]"
173
+ task task_name.to_sym, :count do |_, args|
174
+ ParallelTests::Tasks.run_in_parallel(
175
+ [$0, "db:#{task_name}", "RAILS_ENV=#{ParallelTests::Tasks.rails_env}"],
176
+ args
177
+ )
178
+ end
154
179
  end
155
180
 
156
- desc "Drop test databases via db:drop --> parallel:drop[num_cpus]"
157
- task :drop, :count do |_, args|
158
- ParallelTests::Tasks.run_in_parallel(
159
- [
160
- $0,
161
- "db:drop",
162
- "RAILS_ENV=#{ParallelTests::Tasks.rails_env}",
163
- "DISABLE_DATABASE_ENVIRONMENT_CHECK=1"
164
- ],
165
- args
166
- )
181
+ ParallelTests::Tasks.for_each_database do |name|
182
+ task_name = 'drop'
183
+ task_name += ":#{name}" if name
184
+ desc "Drop test#{" #{name}" if name} database via db:#{task_name} --> parallel:#{task_name}[num_cpus]"
185
+ task task_name.to_sym, :count do |_, args|
186
+ ParallelTests::Tasks.run_in_parallel(
187
+ [
188
+ $0,
189
+ "db:#{task_name}",
190
+ "RAILS_ENV=#{ParallelTests::Tasks.rails_env}",
191
+ "DISABLE_DATABASE_ENVIRONMENT_CHECK=1"
192
+ ],
193
+ args
194
+ )
195
+ end
167
196
  end
168
197
 
169
198
  desc "Update test databases by dumping and loading --> parallel:prepare[num_cpus]"
@@ -190,12 +219,16 @@ namespace :parallel do
190
219
  end
191
220
 
192
221
  # when dumping/resetting takes too long
193
- desc "Update test databases via db:migrate --> parallel:migrate[num_cpus]"
194
- task :migrate, :count do |_, args|
195
- ParallelTests::Tasks.run_in_parallel(
196
- [$0, "db:migrate", "RAILS_ENV=#{ParallelTests::Tasks.rails_env}"],
197
- args
198
- )
222
+ ParallelTests::Tasks.for_each_database do |name|
223
+ task_name = 'migrate'
224
+ task_name += ":#{name}" if name
225
+ desc "Update test#{" #{name}" if name} database via db:#{task_name} --> parallel:#{task_name}[num_cpus]"
226
+ task task_name.to_sym, :count do |_, args|
227
+ ParallelTests::Tasks.run_in_parallel(
228
+ [$0, "db:#{task_name}", "RAILS_ENV=#{ParallelTests::Tasks.rails_env}"],
229
+ args
230
+ )
231
+ end
199
232
  end
200
233
 
201
234
  desc "Rollback test databases via db:rollback --> parallel:rollback[num_cpus]"
@@ -207,16 +240,24 @@ namespace :parallel do
207
240
  end
208
241
 
209
242
  # just load the schema (good for integration server <-> no development db)
210
- desc "Load dumped schema for test databases via db:schema:load --> parallel:load_schema[num_cpus]"
211
- task :load_schema, :count do |_, args|
212
- command = [
213
- $0,
214
- ParallelTests::Tasks.purge_before_load,
215
- "db:schema:load",
216
- "RAILS_ENV=#{ParallelTests::Tasks.rails_env}",
217
- "DISABLE_DATABASE_ENVIRONMENT_CHECK=1"
218
- ]
219
- ParallelTests::Tasks.run_in_parallel(ParallelTests::Tasks.suppress_schema_load_output(command), args)
243
+ ParallelTests::Tasks.for_each_database do |name|
244
+ rails_task = 'db:schema:load'
245
+ rails_task += ":#{name}" if name
246
+
247
+ task_name = 'load_schema'
248
+ task_name += ":#{name}" if name
249
+
250
+ desc "Load dumped schema for test#{" #{name}" if name} database via #{rails_task} --> parallel:#{task_name}[num_cpus]"
251
+ task task_name.to_sym, :count do |_, args|
252
+ command = [
253
+ $0,
254
+ ParallelTests::Tasks.purge_before_load,
255
+ rails_task,
256
+ "RAILS_ENV=#{ParallelTests::Tasks.rails_env}",
257
+ "DISABLE_DATABASE_ENVIRONMENT_CHECK=1"
258
+ ]
259
+ ParallelTests::Tasks.run_in_parallel(ParallelTests::Tasks.suppress_schema_load_output(command), args)
260
+ end
220
261
  end
221
262
 
222
263
  # load the structure from the structure.sql file
@@ -238,8 +238,9 @@ module ParallelTests
238
238
  suffix_pattern = options[:suffix] || test_suffix
239
239
  include_pattern = options[:pattern] || //
240
240
  exclude_pattern = options[:exclude_pattern]
241
+ allow_duplicates = options[:allow_duplicates]
241
242
 
242
- (tests || []).flat_map do |file_or_folder|
243
+ files = (tests || []).flat_map do |file_or_folder|
243
244
  if File.directory?(file_or_folder)
244
245
  files = files_in_folder(file_or_folder, options)
245
246
  files = files.grep(suffix_pattern).grep(include_pattern)
@@ -248,7 +249,9 @@ module ParallelTests
248
249
  else
249
250
  file_or_folder
250
251
  end
251
- end.uniq
252
+ end
253
+
254
+ allow_duplicates ? files : files.uniq
252
255
  end
253
256
 
254
257
  def files_in_folder(folder, options = {})
@@ -290,7 +293,7 @@ module ParallelTests
290
293
  end
291
294
 
292
295
  def report_process_command?(options)
293
- options[:verbose] || options[:verbose_command]
296
+ options[:verbose] || options[:verbose_process_command]
294
297
  end
295
298
  end
296
299
  end
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module ParallelTests
3
- VERSION = '4.4.0'
3
+ VERSION = '4.7.1'
4
4
  end
@@ -44,6 +44,8 @@ module ParallelTests
44
44
 
45
45
  def stop_all_processes
46
46
  pids.all.each { |pid| Process.kill(:INT, pid) }
47
+ rescue Errno::ESRCH
48
+ # Process already terminated, do nothing
47
49
  end
48
50
 
49
51
  # copied from http://github.com/carlhuda/bundler Bundler::SharedHelpers#find_gemfile
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: 4.4.0
4
+ version: 4.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Grosser
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-12-25 00:00:00.000000000 Z
11
+ date: 2024-04-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parallel
@@ -69,8 +69,8 @@ licenses:
69
69
  - MIT
70
70
  metadata:
71
71
  bug_tracker_uri: https://github.com/grosser/parallel_tests/issues
72
- documentation_uri: https://github.com/grosser/parallel_tests/blob/v4.4.0/Readme.md
73
- source_code_uri: https://github.com/grosser/parallel_tests/tree/v4.4.0
72
+ documentation_uri: https://github.com/grosser/parallel_tests/blob/v4.7.1/Readme.md
73
+ source_code_uri: https://github.com/grosser/parallel_tests/tree/v4.7.1
74
74
  wiki_uri: https://github.com/grosser/parallel_tests/wiki
75
75
  post_install_message:
76
76
  rdoc_options: []
@@ -87,7 +87,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
87
87
  - !ruby/object:Gem::Version
88
88
  version: '0'
89
89
  requirements: []
90
- rubygems_version: 3.3.3
90
+ rubygems_version: 3.4.10
91
91
  signing_key:
92
92
  specification_version: 4
93
93
  summary: Run Test::Unit / RSpec / Cucumber / Spinach in parallel