friendlyfashion-parallel_tests 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
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