parallel_tests 3.3.0 → 3.6.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 630376174bbe4941703500d82264c43c0a8b42c3a490b1df9dbe174de6fb58a3
4
- data.tar.gz: 2e37c805bb3ef70476ffb9e9e9881d8f6467741bee4146e27a3ab04542c68f23
3
+ metadata.gz: 05ee67a0bc76b53a3da04722d4d0d1b2ab5d82373b40255edd3ece18f486e026
4
+ data.tar.gz: 2a3c9a39d71ccebe4d938f4005798c3aab95d5d9f9be6a8da50e1b4c5f474a6a
5
5
  SHA512:
6
- metadata.gz: 5efe758f85900c7990d52c31b1f1aa3b1f6ab3e2939a3318eeddc275c6efa8d218d7d137efd61cfe5c701a225b3cf74a676690eef949c2033942baa13f6c3972
7
- data.tar.gz: 434ac657ff8c2f9f5c253cc784ee0de49119391ef195b834a77e9b82b7b485b6f536c9207addfe9e08f09e2026ffd9410db4fdb373498989ff9d5fb1ed003757
6
+ metadata.gz: d755fbc5e33402153ab3db7ca7f01ac035650b2f84ceb22c5d860bd824d2b1fe2e530b84a5266702f1089f55737f21d6b110255125cfbfa28074ad95e1a22eea
7
+ data.tar.gz: 74a6c4dd4c6a027113a59b1240b287906600adc00062a010462f0c4f3bb6934ba2b781a510844b8e9f5b0fee1d4de5e8523008b8b8b29e8ab520d6cbff593a90
data/Readme.md CHANGED
@@ -37,6 +37,9 @@ test:
37
37
  ### Copy development schema (repeat after migrations)
38
38
  rake parallel:prepare
39
39
 
40
+ ### Run migrations in additional database(s) (repeat after migrations)
41
+ rake parallel:migrate
42
+
40
43
  ### Setup environment from scratch (create db and loads schema, useful for CI)
41
44
  rake parallel:setup
42
45
 
@@ -142,17 +145,19 @@ Add the following to your `.rspec_parallel` (or `.rspec`) :
142
145
  RSpec: FailuresLogger
143
146
  -----------------------
144
147
 
145
- Produce pasteable command-line snippets for each failed example.
148
+ Produce pastable command-line snippets for each failed example. For example:
146
149
 
147
- E.g.
150
+ ```bash
151
+ rspec /path/to/my_spec.rb:123 # should do something
152
+ ```
148
153
 
149
- rspec /path/to/my_spec.rb:123 # should do something
150
-
151
- Add the following to your `.rspec_parallel` (or `.rspec`) :
154
+ Add to `.rspec_parallel` or use as CLI flag:
152
155
 
153
156
  --format progress
154
157
  --format ParallelTests::RSpec::FailuresLogger --out tmp/failing_specs.log
155
158
 
159
+ (Not needed to retry failures, for that pass [--only-failures](https://relishapp.com/rspec/rspec-core/docs/command-line/only-failures) to rspec)
160
+
156
161
  Cucumber: FailuresLogger
157
162
  -----------------------
158
163
 
@@ -205,10 +210,19 @@ Options are:
205
210
  default - runtime when runtime log is filled otherwise filesize
206
211
  -m, --multiply-processes [FLOAT] use given number as a multiplier of processes to run
207
212
  -s, --single [PATTERN] Run all matching files in the same process
208
- -i, --isolate Do not run any other tests in the group used by --single(-s).
213
+ -i, --isolate Do not run any other tests in the group used by --single(-s).
209
214
  Automatically turned on if --isolate-n is set above 0.
210
- --isolate-n Number of processes for isolated groups. Default to 1 when --isolate is on.
211
- --only-group INT[, INT]
215
+ --isolate-n Number of processes for isolated groups. Default to 1 when --isolate is on.
216
+ --specify-groups [SPECS] Use 'specify-groups' if you want to specify multiple specs running in multiple
217
+ processes in a specific formation. Commas indicate specs in the same process,
218
+ pipes indicate specs in a new process. Cannot use with --single, --isolate, or
219
+ --isolate-n. Ex.
220
+ Ex.
221
+ $ parallel_tests -n 3 . --specify-groups '1_spec.rb,2_spec.rb|3_spec.rb'
222
+ Process 1 will contain 1_spec.rb and 2_spec.rb
223
+ Process 2 will contain 3_spec.rb
224
+ Process 3 will contain all other specs
225
+ --only-group INT[,INT]
212
226
  -e, --exec [COMMAND] execute this code parallel and with ENV['TEST_ENV_NUMBER']
213
227
  -o, --test-options '[OPTIONS]' execute test commands with those options
214
228
  -t, --type [TYPE] test(default) / rspec / cucumber / spinach
@@ -282,7 +296,7 @@ TIPS
282
296
  `export PARALLEL_TEST_FIRST_IS_1=true` will provide the same result
283
297
  - [email_spec and/or action_mailer_cache_delivery](https://github.com/grosser/parallel_tests/wiki)
284
298
  - [zeus-parallel_tests](https://github.com/sevos/zeus-parallel_tests)
285
- - [Distributed parallel test (e.g. Travis Support)](https://github.com/grosser/parallel_tests/wiki/Distributed-Parallel-Tests-and-Travis-Support)
299
+ - [Distributed Parallel Tests on CI systems)](https://github.com/grosser/parallel_tests/wiki/Distributed-Parallel-Tests-on-CI-systems) learn how `parallel_tests` can run on distributed servers such as Travis and GitLab-CI. Also shows you how to use parallel_tests without adding `TEST_ENV_NUMBER`-backends
286
300
  - [Capybara setup](https://github.com/grosser/parallel_tests/wiki)
287
301
  - [Sphinx setup](https://github.com/grosser/parallel_tests/wiki)
288
302
  - [Capistrano setup](https://github.com/grosser/parallel_tests/wiki/Remotely-with-capistrano) let your tests run on a big box instead of your laptop
@@ -378,6 +392,8 @@ inspired by [pivotal labs](https://blog.pivotal.io/labs/labs/parallelize-your-rs
378
392
  - [Calaway](https://github.com/calaway)
379
393
  - [alboyadjian](https://github.com/alboyadjian)
380
394
  - [Nathan Broadbent](https://github.com/ndbroadbent)
395
+ - [Vikram B Kumar](https://github.com/v-kumar)
396
+ - [Joshua Pinter](https://github.com/joshuapinter)
381
397
 
382
398
  [Michael Grosser](http://grosser.it)<br/>
383
399
  michael@grosser.it<br/>
@@ -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("../..", __FILE__)
5
+ root = File.expand_path('..', __dir__)
5
6
  $LOAD_PATH << "#{root}/lib" if File.exist?("#{root}/Gemfile")
6
7
 
7
8
  require "parallel_tests"
data/bin/parallel_rspec 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("../..", __FILE__)
5
+ root = File.expand_path('..', __dir__)
5
6
  $LOAD_PATH << "#{root}/lib" if File.exist?("#{root}/Gemfile")
6
7
 
7
8
  require "parallel_tests"
data/bin/parallel_spinach 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("../..", __FILE__)
5
+ root = File.expand_path('..', __dir__)
5
6
  $LOAD_PATH << "#{root}/lib" if File.exist?("#{root}/Gemfile")
6
7
 
7
8
  require "parallel_tests"
data/bin/parallel_test 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("../..", __FILE__)
5
+ root = File.expand_path('..', __dir__)
5
6
  $LOAD_PATH << "#{root}/lib" if File.exist?("#{root}/Gemfile")
6
7
 
7
8
  require "parallel_tests"
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "parallel"
2
3
  require "parallel_tests/railtie" if defined? Rails::Railtie
3
4
  require "rbconfig"
@@ -17,21 +18,19 @@ module ParallelTests
17
18
  count,
18
19
  ENV["PARALLEL_TEST_PROCESSORS"],
19
20
  Parallel.processor_count
20
- ].detect{|c| not c.to_s.strip.empty? }.to_i
21
+ ].detect { |c| !c.to_s.strip.empty? }.to_i
21
22
  end
22
23
 
23
24
  def with_pid_file
24
25
  Tempfile.open('parallel_tests-pidfile') do |f|
25
- begin
26
- ENV['PARALLEL_PID_FILE'] = f.path
27
- # Pids object should be created before threads will start adding pids to it
28
- # Otherwise we would have to use Mutex to prevent creation of several instances
29
- @pids = pids
30
- yield
31
- ensure
32
- ENV['PARALLEL_PID_FILE'] = nil
33
- @pids = nil
34
- end
26
+ ENV['PARALLEL_PID_FILE'] = f.path
27
+ # Pids object should be created before threads will start adding pids to it
28
+ # Otherwise we would have to use Mutex to prevent creation of several instances
29
+ @pids = pids
30
+ yield
31
+ ensure
32
+ ENV['PARALLEL_PID_FILE'] = nil
33
+ @pids = nil
35
34
  end
36
35
  end
37
36
 
@@ -57,7 +56,8 @@ module ParallelTests
57
56
  until !File.directory?(current) || current == previous
58
57
  filename = File.join(current, "Gemfile")
59
58
  return true if File.exist?(filename)
60
- current, previous = File.expand_path("..", current), current
59
+ previous = current
60
+ current = File.expand_path("..", current)
61
61
  end
62
62
 
63
63
  false
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'optparse'
2
3
  require 'tempfile'
3
4
  require 'parallel_tests'
@@ -14,7 +15,7 @@ module ParallelTests
14
15
  ENV['DISABLE_SPRING'] ||= '1'
15
16
 
16
17
  num_processes = ParallelTests.determine_number_of_processes(options[:count])
17
- num_processes = num_processes * (options[:multiply] || 1)
18
+ num_processes *= (options[:multiply] || 1)
18
19
 
19
20
  options[:first_is_1] ||= first_is_1?
20
21
 
@@ -56,12 +57,12 @@ module ParallelTests
56
57
  def run_tests_in_parallel(num_processes, options)
57
58
  test_results = nil
58
59
 
59
- run_tests_proc = -> {
60
+ run_tests_proc = -> do
60
61
  groups = @runner.tests_in_groups(options[:files], num_processes, options)
61
- groups.reject! &:empty?
62
+ groups.reject!(&:empty?)
62
63
 
63
64
  test_results = if options[:only_group]
64
- groups_to_run = options[:only_group].collect{|i| groups[i - 1]}.compact
65
+ groups_to_run = options[:only_group].map { |i| groups[i - 1] }.compact
65
66
  report_number_of_tests(groups_to_run) unless options[:quiet]
66
67
  execute_in_parallel(groups_to_run, groups_to_run.size, options) do |group|
67
68
  run_tests(group, groups_to_run.index(group), 1, options)
@@ -75,7 +76,7 @@ module ParallelTests
75
76
  end
76
77
 
77
78
  report_results(test_results, options) unless options[:quiet]
78
- }
79
+ end
79
80
 
80
81
  if options[:quiet]
81
82
  run_tests_proc.call
@@ -88,7 +89,7 @@ module ParallelTests
88
89
 
89
90
  def run_tests(group, process_number, num_processes, options)
90
91
  if group.empty?
91
- {:stdout => '', :exit_status => 0, :command => '', :seed => nil}
92
+ { stdout: '', exit_status: 0, command: '', seed: nil }
92
93
  else
93
94
  @runner.run_tests(group, process_number, num_processes, options)
94
95
  end
@@ -104,18 +105,16 @@ module ParallelTests
104
105
 
105
106
  def lock(lockfile)
106
107
  File.open(lockfile) do |lock|
107
- begin
108
- lock.flock File::LOCK_EX
109
- yield
110
- ensure
111
- # This shouldn't be necessary, but appears to be
112
- lock.flock File::LOCK_UN
113
- end
108
+ lock.flock File::LOCK_EX
109
+ yield
110
+ ensure
111
+ # This shouldn't be necessary, but appears to be
112
+ lock.flock File::LOCK_UN
114
113
  end
115
114
  end
116
115
 
117
116
  def report_results(test_results, options)
118
- results = @runner.find_results(test_results.map { |result| result[:stdout] }*"")
117
+ results = @runner.find_results(test_results.map { |result| result[:stdout] } * "")
119
118
  puts ""
120
119
  puts @runner.summarize_results(results)
121
120
 
@@ -140,20 +139,31 @@ module ParallelTests
140
139
  def report_number_of_tests(groups)
141
140
  name = @runner.test_file_name
142
141
  num_processes = groups.size
143
- num_tests = groups.map(&:size).inject(0, :+)
142
+ num_tests = groups.map(&:size).sum
144
143
  tests_per_process = (num_processes == 0 ? 0 : num_tests / num_processes)
145
- puts "#{num_processes} processes for #{num_tests} #{name}s, ~ #{tests_per_process} #{name}s per process"
144
+ puts "#{pluralize(num_processes, 'process')} for #{pluralize(num_tests, name)}, ~ #{pluralize(tests_per_process, name)} per process"
146
145
  end
147
146
 
148
- #exit with correct status code so rake parallel:test && echo 123 works
147
+ def pluralize(n, singular)
148
+ if n == 1
149
+ "1 #{singular}"
150
+ elsif singular.end_with?('s', 'sh', 'ch', 'x', 'z')
151
+ "#{n} #{singular}es"
152
+ else
153
+ "#{n} #{singular}s"
154
+ end
155
+ end
156
+
157
+ # exit with correct status code so rake parallel:test && echo 123 works
149
158
  def any_test_failed?(test_results)
150
159
  test_results.any? { |result| result[:exit_status] != 0 }
151
160
  end
152
161
 
153
162
  def parse_options!(argv)
163
+ newline_padding = " " * 37
154
164
  options = {}
155
165
  OptionParser.new do |opts|
156
- opts.banner = <<-BANNER.gsub(/^ /, '')
166
+ opts.banner = <<~BANNER
157
167
  Run all tests in parallel, giving each process ENV['TEST_ENV_NUMBER'] ('', '2', '3', ...)
158
168
 
159
169
  [optional] Only selected files & folders:
@@ -167,61 +177,74 @@ module ParallelTests
167
177
  opts.on("-n [PROCESSES]", Integer, "How many processes to use, default: available CPUs") { |n| options[:count] = n }
168
178
  opts.on("-p", "--pattern [PATTERN]", "run tests matching this regex pattern") { |pattern| options[:pattern] = /#{pattern}/ }
169
179
  opts.on("--exclude-pattern", "--exclude-pattern [PATTERN]", "exclude tests matching this regex pattern") { |pattern| options[:exclude_pattern] = /#{pattern}/ }
170
- opts.on("--group-by [TYPE]", <<-TEXT.gsub(/^ /, '')
171
- group tests by:
172
- found - order of finding files
173
- steps - number of cucumber/spinach steps
174
- scenarios - individual cucumber scenarios
175
- filesize - by size of the file
176
- runtime - info from runtime log
177
- default - runtime when runtime log is filled otherwise filesize
180
+ opts.on(
181
+ "--group-by [TYPE]",
182
+ <<~TEXT.rstrip.split("\n").join("\n#{newline_padding}")
183
+ group tests by:
184
+ found - order of finding files
185
+ steps - number of cucumber/spinach steps
186
+ scenarios - individual cucumber scenarios
187
+ filesize - by size of the file
188
+ runtime - info from runtime log
189
+ default - runtime when runtime log is filled otherwise filesize
178
190
  TEXT
179
- ) { |type| options[:group_by] = type.to_sym }
180
- opts.on("-m [FLOAT]", "--multiply-processes [FLOAT]", Float, "use given number as a multiplier of processes to run") { |multiply| options[:multiply] = multiply }
181
-
182
- opts.on("-s [PATTERN]", "--single [PATTERN]",
183
- "Run all matching files in the same process") do |pattern|
184
-
185
- options[:single_process] ||= []
186
- options[:single_process] << /#{pattern}/
191
+ ) { |type| options[:group_by] = type.to_sym }
192
+ opts.on("-m [FLOAT]", "--multiply-processes [FLOAT]", Float, "use given number as a multiplier of processes to run") do |multiply|
193
+ options[:multiply] = multiply
187
194
  end
188
195
 
189
- opts.on("-i", "--isolate",
190
- "Do not run any other tests in the group used by --single(-s)") do |pattern|
196
+ opts.on("-s [PATTERN]", "--single [PATTERN]", "Run all matching files in the same process") do |pattern|
197
+ (options[:single_process] ||= []) << /#{pattern}/
198
+ end
191
199
 
200
+ opts.on("-i", "--isolate", "Do not run any other tests in the group used by --single(-s)") do
192
201
  options[:isolate] = true
193
202
  end
194
203
 
195
- opts.on("--isolate-n [PROCESSES]",
204
+ opts.on(
205
+ "--isolate-n [PROCESSES]",
196
206
  Integer,
197
- "Use 'isolate' singles with number of processes, default: 1.") do |n|
198
- options[:isolate_count] = n
199
- end
207
+ "Use 'isolate' singles with number of processes, default: 1."
208
+ ) { |n| options[:isolate_count] = n }
209
+
210
+ opts.on(
211
+ "--specify-groups [SPECS]",
212
+ <<~TEXT.rstrip.split("\n").join("\n#{newline_padding}")
213
+ Use 'specify-groups' if you want to specify multiple specs running in multiple
214
+ processes in a specific formation. Commas indicate specs in the same process,
215
+ pipes indicate specs in a new process. Cannot use with --single, --isolate, or
216
+ --isolate-n. Ex.
217
+ $ parallel_tests -n 3 . --specify-groups '1_spec.rb,2_spec.rb|3_spec.rb'
218
+ Process 1 will contain 1_spec.rb and 2_spec.rb
219
+ Process 2 will contain 3_spec.rb
220
+ Process 3 will contain all other specs
221
+ TEXT
222
+ ) { |groups| options[:specify_groups] = groups }
200
223
 
201
- opts.on("--only-group INT[, INT]", Array) { |groups| options[:only_group] = groups.map(&:to_i) }
224
+ opts.on("--only-group INT[,INT]", Array) { |groups| options[:only_group] = groups.map(&:to_i) }
202
225
 
203
226
  opts.on("-e", "--exec [COMMAND]", "execute this code parallel and with ENV['TEST_ENV_NUMBER']") { |path| options[:execute] = path }
204
227
  opts.on("-o", "--test-options '[OPTIONS]'", "execute test commands with those options") { |arg| options[:test_options] = arg.lstrip }
205
228
  opts.on("-t", "--type [TYPE]", "test(default) / rspec / cucumber / spinach") do |type|
206
- begin
207
- @runner = load_runner(type)
208
- rescue NameError, LoadError => e
209
- puts "Runner for `#{type}` type has not been found! (#{e})"
210
- abort
211
- end
229
+ @runner = load_runner(type)
230
+ rescue NameError, LoadError => e
231
+ puts "Runner for `#{type}` type has not been found! (#{e})"
232
+ abort
212
233
  end
213
- opts.on("--suffix [PATTERN]", <<-TEXT.gsub(/^ /, '')
214
- override built in test file pattern (should match suffix):
215
- '_spec\.rb$' - matches rspec files
216
- '_(test|spec).rb$' - matches test or spec files
234
+ opts.on(
235
+ "--suffix [PATTERN]",
236
+ <<~TEXT.rstrip.split("\n").join("\n#{newline_padding}")
237
+ override built in test file pattern (should match suffix):
238
+ '_spec\.rb$' - matches rspec files
239
+ '_(test|spec).rb$' - matches test or spec files
217
240
  TEXT
218
- ) { |pattern| options[:suffix] = /#{pattern}/ }
241
+ ) { |pattern| options[:suffix] = /#{pattern}/ }
219
242
  opts.on("--serialize-stdout", "Serialize stdout output, nothing will be written until everything is done") { options[:serialize_stdout] = true }
220
243
  opts.on("--prefix-output-with-test-env-number", "Prefixes test env number to the output when not using --serialize-stdout") { options[:prefix_output_with_test_env_number] = true }
221
244
  opts.on("--combine-stderr", "Combine stderr into stdout, useful in conjunction with --serialize-stdout") { options[:combine_stderr] = true }
222
245
  opts.on("--non-parallel", "execute same commands but do not in parallel, needs --exec") { options[:non_parallel] = true }
223
246
  opts.on("--no-symlinks", "Do not traverse symbolic links to find test files") { options[:symlinks] = false }
224
- opts.on('--ignore-tags [PATTERN]', 'When counting steps ignore scenarios with tags that match this pattern') { |arg| options[:ignore_tag_pattern] = arg }
247
+ opts.on('--ignore-tags [PATTERN]', 'When counting steps ignore scenarios with tags that match this pattern') { |arg| options[:ignore_tag_pattern] = arg }
225
248
  opts.on("--nice", "execute test commands with low priority.") { options[:nice] = true }
226
249
  opts.on("--runtime-log [PATH]", "Location of previously recorded test runtimes") { |path| options[:runtime_log] = path }
227
250
  opts.on("--allowed-missing [INT]", Integer, "Allowed percentage of missing runtimes (default = 50)") { |percent| options[:allowed_missing_percent] = percent }
@@ -232,13 +255,17 @@ module ParallelTests
232
255
  opts.on("--verbose-process-command", "Displays only the command that will be executed by each process") { options[:verbose_process_command] = true }
233
256
  opts.on("--verbose-rerun-command", "When there are failures, displays the command executed by each process that failed") { options[:verbose_rerun_command] = true }
234
257
  opts.on("--quiet", "Print only tests output") { options[:quiet] = true }
235
- opts.on("-v", "--version", "Show Version") { puts ParallelTests::VERSION; exit }
236
- opts.on("-h", "--help", "Show this.") { puts opts; exit }
258
+ opts.on("-v", "--version", "Show Version") do
259
+ puts ParallelTests::VERSION
260
+ exit 0
261
+ end
262
+ opts.on("-h", "--help", "Show this.") do
263
+ puts opts
264
+ exit 0
265
+ end
237
266
  end.parse!(argv)
238
267
 
239
- if options[:verbose] && options[:quiet]
240
- raise "Both options are mutually exclusive: verbose & quiet"
241
- end
268
+ raise "Both options are mutually exclusive: verbose & quiet" if options[:verbose] && options[:quiet]
242
269
 
243
270
  if options[:count] == 0
244
271
  options.delete(:count)
@@ -247,7 +274,14 @@ module ParallelTests
247
274
 
248
275
  files, remaining = extract_file_paths(argv)
249
276
  unless options[:execute]
250
- abort "Pass files or folders to run" unless files.any?
277
+ if files.empty?
278
+ default_test_folder = @runner.default_test_folder
279
+ if File.directory?(default_test_folder)
280
+ files = [default_test_folder]
281
+ else
282
+ abort "Pass files or folders to run"
283
+ end
284
+ end
251
285
  options[:files] = files.map { |file_path| Pathname.new(file_path).cleanpath.to_s }
252
286
  end
253
287
 
@@ -255,12 +289,18 @@ module ParallelTests
255
289
 
256
290
  options[:group_by] ||= :filesize if options[:only_group]
257
291
 
258
- raise "--group-by found and --single-process are not supported" if options[:group_by] == :found and options[:single_process]
292
+ if options[:group_by] == :found && options[:single_process]
293
+ raise "--group-by found and --single-process are not supported"
294
+ end
259
295
  allowed = [:filesize, :runtime, :found]
260
296
  if !allowed.include?(options[:group_by]) && options[:only_group]
261
297
  raise "--group-by #{allowed.join(" or ")} is required for --only-group"
262
298
  end
263
299
 
300
+ if options[:specify_groups] && (options.keys & [:single_process, :isolate, :isolate_count]).any?
301
+ raise "Can't pass --specify-groups with any of these keys: --single, --isolate, or --isolate-n"
302
+ end
303
+
264
304
  options
265
305
  end
266
306
 
@@ -272,7 +312,7 @@ module ParallelTests
272
312
 
273
313
  def extract_test_options(argv)
274
314
  dash_index = argv.index("--") || -1
275
- argv[dash_index+1..-1]
315
+ argv[dash_index + 1..-1]
276
316
  end
277
317
 
278
318
  def append_test_options(options, argv)
@@ -292,7 +332,7 @@ module ParallelTests
292
332
 
293
333
  def execute_shell_command_in_parallel(command, num_processes, options)
294
334
  runs = if options[:only_group]
295
- options[:only_group].map{|g| g - 1}
335
+ options[:only_group].map { |g| g - 1 }
296
336
  else
297
337
  (0...num_processes).to_a
298
338
  end
@@ -311,13 +351,13 @@ module ParallelTests
311
351
  abort if results.any? { |r| r[:exit_status] != 0 }
312
352
  end
313
353
 
314
- def report_time_taken
315
- seconds = ParallelTests.delta { yield }.to_i
354
+ def report_time_taken(&block)
355
+ seconds = ParallelTests.delta(&block).to_i
316
356
  puts "\nTook #{seconds} seconds#{detailed_duration(seconds)}"
317
357
  end
318
358
 
319
359
  def detailed_duration(seconds)
320
- parts = [ seconds / 3600, seconds % 3600 / 60, seconds % 60 ].drop_while(&:zero?)
360
+ parts = [seconds / 3600, seconds % 3600 / 60, seconds % 60].drop_while(&:zero?)
321
361
  return if parts.size < 2
322
362
  parts = parts.map { |i| "%02d" % i }.join(':').sub(/^0/, '')
323
363
  " (#{parts})"