friendlyfashion-parallel_tests 0.9.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.
Files changed (41) hide show
  1. data/.gitignore +2 -0
  2. data/Gemfile +8 -0
  3. data/Gemfile.lock +44 -0
  4. data/Rakefile +6 -0
  5. data/Readme.md +232 -0
  6. data/ReadmeRails2.md +48 -0
  7. data/bin/parallel_cucumber +2 -0
  8. data/bin/parallel_rspec +2 -0
  9. data/bin/parallel_test +6 -0
  10. data/lib/parallel_tests.rb +30 -0
  11. data/lib/parallel_tests/cli.rb +159 -0
  12. data/lib/parallel_tests/cucumber/gherkin_listener.rb +60 -0
  13. data/lib/parallel_tests/cucumber/runner.rb +90 -0
  14. data/lib/parallel_tests/cucumber/runtime_logger.rb +58 -0
  15. data/lib/parallel_tests/grouper.rb +53 -0
  16. data/lib/parallel_tests/railtie.rb +8 -0
  17. data/lib/parallel_tests/rspec/failures_logger.rb +44 -0
  18. data/lib/parallel_tests/rspec/logger_base.rb +52 -0
  19. data/lib/parallel_tests/rspec/runner.rb +59 -0
  20. data/lib/parallel_tests/rspec/runtime_logger.rb +34 -0
  21. data/lib/parallel_tests/rspec/summary_logger.rb +19 -0
  22. data/lib/parallel_tests/tasks.rb +134 -0
  23. data/lib/parallel_tests/test/runner.rb +134 -0
  24. data/lib/parallel_tests/test/runtime_logger.rb +92 -0
  25. data/lib/parallel_tests/version.rb +3 -0
  26. data/parallel_tests.gemspec +14 -0
  27. data/spec/integration_spec.rb +244 -0
  28. data/spec/parallel_tests/cli_spec.rb +36 -0
  29. data/spec/parallel_tests/cucumber/gherkin_listener_spec.rb +48 -0
  30. data/spec/parallel_tests/cucumber/runner_spec.rb +173 -0
  31. data/spec/parallel_tests/grouper_spec.rb +52 -0
  32. data/spec/parallel_tests/rspec/failure_logger_spec.rb +82 -0
  33. data/spec/parallel_tests/rspec/runner_spec.rb +178 -0
  34. data/spec/parallel_tests/rspec/runtime_logger_spec.rb +76 -0
  35. data/spec/parallel_tests/rspec/summary_logger_spec.rb +37 -0
  36. data/spec/parallel_tests/tasks_spec.rb +151 -0
  37. data/spec/parallel_tests/test/runner_spec.rb +273 -0
  38. data/spec/parallel_tests/test/runtime_logger_spec.rb +84 -0
  39. data/spec/parallel_tests_spec.rb +73 -0
  40. data/spec/spec_helper.rb +151 -0
  41. metadata +109 -0
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ *.sh
2
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source :rubygems
2
+ gemspec
3
+
4
+ gem 'bump'
5
+ gem 'test-unit', :platform => :ruby_19
6
+ gem 'rspec', '>=2.4'
7
+ gem 'cucumber'
8
+ gem 'rake'
data/Gemfile.lock ADDED
@@ -0,0 +1,44 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ parallel_tests (0.9.0)
5
+ parallel
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ builder (3.0.0)
11
+ bump (0.3.8)
12
+ cucumber (1.1.4)
13
+ builder (>= 2.1.2)
14
+ diff-lcs (>= 1.1.2)
15
+ gherkin (~> 2.7.1)
16
+ json (>= 1.4.6)
17
+ term-ansicolor (>= 1.0.6)
18
+ diff-lcs (1.1.3)
19
+ gherkin (2.7.6)
20
+ json (>= 1.4.6)
21
+ json (1.7.5)
22
+ parallel (0.6.1)
23
+ rake (10.0.3)
24
+ rspec (2.12.0)
25
+ rspec-core (~> 2.12.0)
26
+ rspec-expectations (~> 2.12.0)
27
+ rspec-mocks (~> 2.12.0)
28
+ rspec-core (2.12.2)
29
+ rspec-expectations (2.12.1)
30
+ diff-lcs (~> 1.1.3)
31
+ rspec-mocks (2.12.1)
32
+ term-ansicolor (1.0.7)
33
+ test-unit (2.4.4)
34
+
35
+ PLATFORMS
36
+ ruby
37
+
38
+ DEPENDENCIES
39
+ bump
40
+ cucumber
41
+ parallel_tests!
42
+ rake
43
+ rspec (>= 2.4)
44
+ test-unit
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require 'bump/tasks'
2
+ require 'bundler/gem_tasks'
3
+
4
+ task :default do
5
+ sh "rspec spec/"
6
+ end
data/Readme.md ADDED
@@ -0,0 +1,232 @@
1
+ Speedup Test::Unit + RSpec + Cucumber by running parallel on multiple CPUs (or cores).<br/>
2
+ ParallelTests splits tests into even groups(by number of tests or runtime) and runs each group in a single process with its own database.
3
+
4
+ [upgrading from 0.6 ?](https://github.com/grosser/parallel_tests/wiki/Upgrading-0.6.x-to-0.7.x)
5
+
6
+ Setup for Rails
7
+ ===============
8
+ [still using Rails 2?](https://github.com/grosser/parallel_tests/blob/master/ReadmeRails2.md)
9
+
10
+ ### Install
11
+ If you use RSpec: ensure you got >= 2.4
12
+
13
+ As gem
14
+
15
+ ```ruby
16
+ # add to Gemfile
17
+ gem "parallel_tests", :group => :development
18
+ ```
19
+ OR as plugin
20
+
21
+ rails plugin install git://github.com/grosser/parallel_tests.git
22
+
23
+ ```ruby
24
+ # add to Gemfile
25
+ gem "parallel", :group => :development
26
+ ```
27
+
28
+ ### Add to `config/database.yml`
29
+ ParallelTests uses 1 database per test-process, 2 processes will use `*_test` and `*_test2`.
30
+
31
+ ```yaml
32
+ test:
33
+ database: yourproject_test<%= ENV['TEST_ENV_NUMBER'] %>
34
+ ```
35
+
36
+ ### Create additional database(s)
37
+ rake parallel:create
38
+
39
+ ### Copy development schema (repeat after migrations)
40
+ rake parallel:prepare
41
+
42
+ ### Run!
43
+ rake parallel:test # Test::Unit
44
+ rake parallel:spec # RSpec
45
+ rake parallel:features # Cucumber
46
+
47
+ rake parallel:test[1] --> force 1 CPU --> 86 seconds
48
+ rake parallel:test --> got 2 CPUs? --> 47 seconds
49
+ rake parallel:test --> got 4 CPUs? --> 26 seconds
50
+ ...
51
+
52
+ Test by pattern (e.g. use one integration server per subfolder / see if you broke any 'user'-related tests)
53
+
54
+ rake parallel:test[^test/unit] # every test file in test/unit folder
55
+ rake parallel:test[user] # run users_controller + user_helper + user tests
56
+ rake parallel:test['user|product'] # run user and product related tests
57
+
58
+
59
+ ### Example output
60
+
61
+ 2 processes for 210 specs, ~ 105 specs per process
62
+ ... test output ...
63
+
64
+ 843 examples, 0 failures, 1 pending
65
+
66
+ Took 29.925333 seconds
67
+
68
+ Loggers
69
+ ===================
70
+
71
+ Even process runtimes
72
+ -----------------
73
+
74
+ Log test runtime to give each process the same runtime.
75
+
76
+ Rspec: Add to your `.rspec_parallel` (or `.rspec`) :
77
+
78
+ If installed as plugin: -I vendor/plugins/parallel_tests/lib
79
+ --format progress
80
+ --format ParallelTests::RSpec::RuntimeLogger --out tmp/parallel_runtime_rspec.log
81
+
82
+ Test::Unit: Add to your `test_helper.rb`:
83
+ ```ruby
84
+ require 'parallel_tests/test/runtime_logger'
85
+ ```
86
+
87
+ RSpec: SummaryLogger
88
+ --------------------
89
+
90
+ This logger logs the test output without the different processes overwriting each other.
91
+
92
+ Add the following to your `.rspec_parallel` (or `.rspec`) :
93
+
94
+ If installed as plugin: -I vendor/plugins/parallel_tests/lib
95
+ --format progress
96
+ --format ParallelTests::RSpec::SummaryLogger --out tmp/spec_summary.log
97
+
98
+ RSpec: FailuresLogger
99
+ -----------------------
100
+
101
+ This logger produces pasteable command-line snippets for each failed example.
102
+
103
+ E.g.
104
+
105
+ rspec /path/to/my_spec.rb:123 # should do something
106
+
107
+ Add the following to your `.rspec_parallel` (or `.rspec`) :
108
+
109
+ If installed as plugin: -I vendor/plugins/parallel_tests/lib
110
+ --format progress
111
+ --format ParallelTests::RSpec::FailuresLogger --out tmp/failing_specs.log
112
+
113
+ Setup for non-rails
114
+ ===================
115
+ gem install parallel_tests
116
+ # go to your project dir
117
+ parallel_test test/
118
+ parallel_rspec spec/
119
+ parallel_cucumber features/
120
+
121
+ - use ENV['TEST_ENV_NUMBER'] inside your tests to select separate db/memcache/etc.
122
+ - Only run selected files & folders:
123
+
124
+ parallel_test test/bar test/baz/foo_text.rb
125
+
126
+ Options are:
127
+
128
+ -n [PROCESSES] How many processes to use, default: available CPUs
129
+ -p, --pattern [PATTERN] run tests matching this pattern
130
+ --group-by [TYPE] group tests by:
131
+ found - order of finding files
132
+ steps - number of cucumber steps
133
+ default - runtime or filesize
134
+ -m, --multiply-processes [FLOAT] use given number as a multiplier of processes to run
135
+ -s, --single [PATTERN] Run all matching files in the same process
136
+ -i, --isolate Do not run any other tests in the group used by --single(-s)
137
+ -e, --exec [COMMAND] execute this code parallel and with ENV['TEST_ENV_NUM']
138
+ -o, --test-options '[OPTIONS]' execute test commands with those options
139
+ -t, --type [TYPE] test(default) / rspec / cucumber
140
+ --non-parallel execute same commands but do not in parallel, needs --exec
141
+ --no-symlinks Do not traverse symbolic links to find test files
142
+ -v, --version Show Version
143
+ -h, --help Show this.
144
+
145
+ You can run any kind of code in parallel with -e / --execute
146
+
147
+ parallel_test -n 5 -e 'ruby -e "puts %[hello from process #{ENV[:TEST_ENV_NUMBER.to_s].inspect}]"'
148
+ hello from process "2"
149
+ hello from process ""
150
+ hello from process "3"
151
+ hello from process "5"
152
+ hello from process "4"
153
+
154
+ <table>
155
+ <tr><td></td><td>1 Process</td><td>2 Processes</td><td>4 Processes</td></tr>
156
+ <tr><td>RSpec spec-suite</td><td>18s</td><td>14s</td><td>10s</td></tr>
157
+ <tr><td>Rails-ActionPack</td><td>88s</td><td>53s</td><td>44s</td></tr>
158
+ </table>
159
+
160
+ TIPS
161
+ ====
162
+ - [RSpec] add a `.rspec_parallel` to use different options, e.g. **no --drb**
163
+ - [RSpec] delete `script/spec`
164
+ - [[Spork](https://github.com/sporkrb/spork)] does not work with parallel_tests
165
+ - [RSpec] remove --loadby from you spec/*.opts
166
+ - [RSpec] Instantly see failures (instead of just a red F) with [rspec-instafail](https://github.com/grosser/rspec-instafail)
167
+ - [Bundler] if you have a `Gemfile` then `bundle exec` will be used to run tests
168
+ - [Cucumber] add a `parallel: foo` profile to your `config/cucumber.yml` and it will be used to run parallel tests
169
+ - [Capybara setup](https://github.com/grosser/parallel_tests/wiki)
170
+ - [Sphinx setup](https://github.com/grosser/parallel_tests/wiki)
171
+ - [Capistrano setup](https://github.com/grosser/parallel_tests/wiki/Remotely-with-capistrano) let your tests run on a big box instead of your laptop
172
+ - [SQL schema format] use :ruby schema format to get faster parallel:prepare`
173
+ - `export PARALLEL_TEST_PROCESSORS=X` in your environment and parallel_tests will use this number of processors by default
174
+ - [ZSH] use quotes to use rake arguments `rake "parallel:prepare[3]"`
175
+ - [email_spec and/or action_mailer_cache_delivery](https://github.com/grosser/parallel_tests/wiki)
176
+ - [Memcached] use different namespaces e.g. `config.cache_store = ..., :namespace => "test_#{ENV['TEST_ENV_NUMBER']}"`
177
+
178
+ TODO
179
+ ====
180
+ - fix tests vs cucumber >= 1.2 `unknown option --format`
181
+ - add tests for the rake tasks, maybe generate a rails project ...
182
+ - add unit tests for cucumber runtime formatter
183
+ - make jRuby compatible [basics](http://yehudakatz.com/2009/07/01/new-rails-isolation-testing/)
184
+ - make windows compatible
185
+
186
+ Authors
187
+ ====
188
+ inspired by [pivotal labs](http://pivotallabs.com/users/miked/blog/articles/849-parallelize-your-rspec-suite)
189
+
190
+ ### [Contributors](http://github.com/grosser/parallel_tests/contributors)
191
+ - [Charles Finkel](http://charlesfinkel.com/)
192
+ - [Indrek Juhkam](http://urgas.eu)
193
+ - [Jason Morrison](http://jayunit.net)
194
+ - [jinzhu](http://github.com/jinzhu)
195
+ - [Joakim Kolsjö](http://www.rubyblocks.se)
196
+ - [Kevin Scaldeferri](http://kevin.scaldeferri.com/blog/)
197
+ - [Kpumuk](http://kpumuk.info/)
198
+ - [Maksim Horbul](http://github.com/mhorbul)
199
+ - [Pivotal Labs](http://www.pivotallabs.com)
200
+ - [Rohan Deshpande](http://github.com/rdeshpande)
201
+ - [Tchandy](http://thiagopradi.net/)
202
+ - [Terence Lee](http://hone.heroku.com/)
203
+ - [Will Bryant](http://willbryant.net/)
204
+ - [Fred Wu](http://fredwu.me)
205
+ - [xxx](https://github.com/xxx)
206
+ - [Levent Ali](http://purebreeze.com/)
207
+ - [Michael Kintzer](https://github.com/rockrep)
208
+ - [nathansobo](https://github.com/nathansobo)
209
+ - [Joe Yates](http://titusd.co.uk)
210
+ - [asmega](http://www.ph-lee.com)
211
+ - [Doug Barth](https://github.com/dougbarth)
212
+ - [Geoffrey Hichborn](https://github.com/phene)
213
+ - [Trae Robrock](https://github.com/trobrock)
214
+ - [Lawrence Wang](https://github.com/levity)
215
+ - [Sean Walbran](https://github.com/seanwalbran)
216
+ - [Lawrence Wang](https://github.com/levity)
217
+ - [Potapov Sergey](https://github.com/greyblake)
218
+ - [Łukasz Tackowiak](https://github.com/lukasztackowiak)
219
+ - [Pedro Carriço](https://github.com/pedrocarrico)
220
+ - [Pablo Manrubia Díez](https://github.com/pmanrubia)
221
+ - [Slawomir Smiechura](https://github.com/ssmiech)
222
+ - [Georg Friedrich](https://github.com/georg)
223
+ - [R. Tyler Croy](https://github.com/rtyler)
224
+ - [Ulrich Berkmüller](https://github.com/ulrich-berkmueller)
225
+ - [Grzegorz Derebecki](https://github.com/madmax)
226
+ - [Florian Motlik](https://github.com/flomotlik)
227
+ - [Artem Kuzko](https://github.com/akuzko)
228
+ - [Zeke Fast](https://github.com/zekefast)
229
+
230
+ [Michael Grosser](http://grosser.it)<br/>
231
+ michael@grosser.it<br/>
232
+ License: MIT
data/ReadmeRails2.md ADDED
@@ -0,0 +1,48 @@
1
+ ### Install
2
+
3
+ As gem
4
+
5
+ gem install parallel_tests
6
+
7
+ # add to config/environments/development.rb
8
+ config.gem "parallel_tests"
9
+
10
+ # add to Rakefile
11
+ begin; require 'parallel_tests/tasks'; rescue LoadError; end
12
+
13
+ OR as plugin
14
+
15
+ gem install parallel
16
+
17
+ # add to config/environments/development.rb
18
+ config.gem "parallel"
19
+
20
+ ./script/plugin install git://github.com/grosser/parallel_tests.git
21
+
22
+ # add to Rakefile
23
+ begin; require 'vendor/plugins/parallel_tests/lib/parallel_tests/tasks'; rescue LoadError; end
24
+
25
+
26
+ Even process runtimes
27
+ -----------------
28
+
29
+ RSpec 1.x:
30
+ --format progress
31
+ --require parallel_tests/rspec/runtime_logger
32
+ --format ParallelTests::RSpec::RuntimeLogger:tmp/parallel_runtime_rspec.log
33
+
34
+ SpecSummaryLogger
35
+ --------------------
36
+
37
+ RSpec 1.x:
38
+ --format progress
39
+ --require parallel_tests/rspec/summary_logger
40
+ --format ParallelTests::RSpec::SummaryLogger:tmp/spec_summary.log
41
+
42
+ SpecFailuresLogger
43
+ -----------------------
44
+
45
+ RSpec 1.x:
46
+ --format progress
47
+ --require parallel_tests/rspec/failures_logger
48
+ --format ParallelTests::RSpec::FailuresLogger:tmp/failing_specs.log
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env ruby
2
+ exec "#{File.join(File.dirname(__FILE__), 'parallel_test')} -t cucumber #{ARGV.map{|a| "'#{a}'" } * ' '}"
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env ruby
2
+ exec "#{File.join(File.dirname(__FILE__), 'parallel_test')} -t rspec #{ARGV.map{|a| "'#{a}'" } * ' '}"
data/bin/parallel_test ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ $LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
3
+ require "parallel_tests"
4
+ require "parallel_tests/cli"
5
+
6
+ ParallelTest::CLI.run(ARGV)
@@ -0,0 +1,30 @@
1
+ require 'parallel'
2
+ require 'parallel_tests/version'
3
+ require 'parallel_tests/grouper'
4
+ require 'parallel_tests/railtie' if defined? Rails::Railtie
5
+
6
+ module ParallelTests
7
+ def self.determine_number_of_processes(count)
8
+ [
9
+ count,
10
+ ENV['PARALLEL_TEST_PROCESSORS'],
11
+ Parallel.processor_count
12
+ ].detect{|c| not c.to_s.strip.empty? }.to_i
13
+ end
14
+
15
+ # copied from http://github.com/carlhuda/bundler Bundler::SharedHelpers#find_gemfile
16
+ def self.bundler_enabled?
17
+ return true if Object.const_defined?(:Bundler)
18
+
19
+ previous = nil
20
+ current = File.expand_path(Dir.pwd)
21
+
22
+ until !File.directory?(current) || current == previous
23
+ filename = File.join(current, "Gemfile")
24
+ return true if File.exists?(filename)
25
+ current, previous = File.expand_path("..", current), current
26
+ end
27
+
28
+ false
29
+ end
30
+ end
@@ -0,0 +1,159 @@
1
+ require 'optparse'
2
+ require 'parallel_tests/test/runner'
3
+
4
+ module ParallelTest
5
+ module CLI
6
+ def self.run(argv)
7
+ options = parse_options!(argv)
8
+
9
+ num_processes = ParallelTests.determine_number_of_processes(options[:count])
10
+ num_processes = num_processes * (options[:multiply] || 1)
11
+
12
+ if options[:execute]
13
+ execute_shell_command_in_parallel(options[:execute], num_processes, options)
14
+ else
15
+ run_tests_in_parallel(num_processes, options)
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def self.run_tests_in_parallel(num_processes, options)
22
+ test_results = nil
23
+ lib = options[:type] || 'test'
24
+ runner = load_runner_for(lib)
25
+
26
+ report_time_taken do
27
+ groups = runner.tests_in_groups(options[:files], num_processes, options)
28
+ report_number_of_tests(runner, groups)
29
+
30
+ test_results = Parallel.map(groups, :in_processes => groups.size) do |group|
31
+ run_tests(runner, group, groups.index(group), options)
32
+ end
33
+
34
+ report_results(runner, test_results)
35
+ end
36
+
37
+ abort final_fail_message(lib) if any_test_failed?(test_results)
38
+ end
39
+
40
+ def self.run_tests(runner, group, process_number, options)
41
+ if group.empty?
42
+ {:stdout => '', :exit_status => 0}
43
+ else
44
+ runner.run_tests(group, process_number, options)
45
+ end
46
+ end
47
+
48
+ def self.report_results(runner, test_results)
49
+ results = runner.find_results(test_results.map { |result| result[:stdout] }*"")
50
+ puts ""
51
+ puts runner.summarize_results(results)
52
+ end
53
+
54
+ def self.report_number_of_tests(runner, groups)
55
+ name = runner.test_file_name
56
+ num_processes = groups.size
57
+ num_tests = groups.map(&:size).inject(:+)
58
+ puts "#{num_processes} processes for #{num_tests} #{name}s, ~ #{num_tests / groups.size} #{name}s per process"
59
+ end
60
+
61
+ #exit with correct status code so rake parallel:test && echo 123 works
62
+ def self.any_test_failed?(test_results)
63
+ test_results.any? { |result| result[:exit_status] != 0 }
64
+ end
65
+
66
+ def self.load_runner_for(lib)
67
+ require "parallel_tests/#{lib}/runner"
68
+ eval("ParallelTests::#{lib.capitalize.sub('Rspec','RSpec')}::Runner")
69
+ end
70
+
71
+ def self.parse_options!(argv)
72
+ options = {}
73
+ OptionParser.new do |opts|
74
+ opts.banner = <<BANNER
75
+ Run all tests in parallel, giving each process ENV['TEST_ENV_NUMBER'] ('', '2', '3', ...)
76
+
77
+ [optional] Only run selected files & folders:
78
+ parallel_test test/bar test/baz/xxx_text.rb
79
+
80
+ Options are:
81
+ BANNER
82
+ opts.on("-n [PROCESSES]", Integer, "How many processes to use, default: available CPUs") { |n| options[:count] = n }
83
+ opts.on("-p", "--pattern [PATTERN]", "run tests matching this pattern") { |pattern| options[:pattern] = /#{pattern}/ }
84
+ opts.on("--group-by [TYPE]", <<-TEXT
85
+ group tests by:
86
+ found - order of finding files
87
+ steps - number of cucumber steps
88
+ default - runtime or filesize
89
+ TEXT
90
+ ) { |type| options[:group_by] = type.to_sym }
91
+ opts.on("-m [FLOAT]", "--multiply-processes [FLOAT]", Float, "use given number as a multiplier of processes to run") { |multiply| options[:multiply] = multiply }
92
+
93
+ opts.on("-s [PATTERN]", "--single [PATTERN]",
94
+ "Run all matching files in the same process") do |pattern|
95
+
96
+ options[:single_process] ||= []
97
+ options[:single_process] << /#{pattern}/
98
+ end
99
+
100
+ opts.on("-i", "--isolate",
101
+ "Do not run any other tests in the group used by --single(-s)") do |pattern|
102
+
103
+ options[:isolate] = true
104
+ end
105
+
106
+ opts.on("-e", "--exec [COMMAND]", "execute this code parallel and with ENV['TEST_ENV_NUM']") { |path| options[:execute] = path }
107
+ opts.on("-o", "--test-options '[OPTIONS]'", "execute test commands with those options") { |arg| options[:test_options] = arg }
108
+ opts.on("-t", "--type [TYPE]", "test(default) / rspec / cucumber") { |type| options[:type] = type }
109
+ opts.on("--non-parallel", "execute same commands but do not in parallel, needs --exec") { options[:non_parallel] = true }
110
+ opts.on("--no-symlinks", "Do not traverse symbolic links to find test files") { options[:symlinks] = false }
111
+ opts.on("--advance-number [NUMBER]", Integer, "Advance test env number by specified number") { |n| options[:advance_number] = n }
112
+ opts.on("-v", "--version", "Show Version") { puts ParallelTests::VERSION; exit }
113
+ opts.on("-h", "--help", "Show this.") { puts opts; exit }
114
+ end.parse!(argv)
115
+
116
+ raise "--group-by found and --single-process are not supported" if options[:group_by] == :found and options[:single_process]
117
+
118
+ if options[:count] == 0
119
+ options.delete(:count)
120
+ options[:non_parallel] = true
121
+ end
122
+
123
+ options[:files] = argv
124
+ options
125
+ end
126
+
127
+ def self.execute_shell_command_in_parallel(command, num_processes, options)
128
+ runs = (0...num_processes).to_a
129
+ results = if options[:non_parallel]
130
+ runs.map do |i|
131
+ ParallelTests::Test::Runner.execute_command(command, i, options)
132
+ end
133
+ else
134
+ Parallel.map(runs, :in_processes => num_processes) do |i|
135
+ ParallelTests::Test::Runner.execute_command(command, i, options)
136
+ end
137
+ end.flatten
138
+
139
+ abort if results.any? { |r| r[:exit_status] != 0 }
140
+ end
141
+
142
+ def self.report_time_taken
143
+ start = Time.now
144
+ yield
145
+ puts "\nTook #{Time.now - start} seconds"
146
+ end
147
+
148
+ def self.final_fail_message(lib)
149
+ fail_message = "#{lib.capitalize}s Failed"
150
+ fail_message = "\e[31m#{fail_message}\e[0m" if use_colors?
151
+
152
+ fail_message
153
+ end
154
+
155
+ def self.use_colors?
156
+ $stdout.tty?
157
+ end
158
+ end
159
+ end