moxiesoft_parallel_tests 0.4.12

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.
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ *.sh
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source :rubygems
2
+
3
+ gem 'parallel'
4
+
5
+ group :dev do
6
+ gem 'rake'
7
+ gem 'rspec', '~>2'
8
+ gem 'jeweler'
9
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,34 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ diff-lcs (1.1.2)
5
+ gemcutter (0.6.1)
6
+ git (1.2.5)
7
+ jeweler (1.4.0)
8
+ gemcutter (>= 0.1.0)
9
+ git (>= 1.2.5)
10
+ rubyforge (>= 2.0.0)
11
+ json_pure (1.4.6)
12
+ parallel (0.5.1)
13
+ rake (0.8.7)
14
+ rspec (2.0.1)
15
+ rspec-core (~> 2.0.1)
16
+ rspec-expectations (~> 2.0.1)
17
+ rspec-mocks (~> 2.0.1)
18
+ rspec-core (2.0.1)
19
+ rspec-expectations (2.0.1)
20
+ diff-lcs (>= 1.1.2)
21
+ rspec-mocks (2.0.1)
22
+ rspec-core (~> 2.0.1)
23
+ rspec-expectations (~> 2.0.1)
24
+ rubyforge (2.0.4)
25
+ json_pure (>= 1.1.7)
26
+
27
+ PLATFORMS
28
+ ruby
29
+
30
+ DEPENDENCIES
31
+ jeweler
32
+ parallel
33
+ rake
34
+ rspec (~> 2)
data/Rakefile ADDED
@@ -0,0 +1,21 @@
1
+ task :default => :spec
2
+ require "rspec/core/rake_task"
3
+ RSpec::Core::RakeTask.new(:spec) do |t|
4
+ t.rspec_opts = '--backtrace --color'
5
+ end
6
+
7
+ begin
8
+ require 'jeweler'
9
+ Jeweler::Tasks.new do |gem|
10
+ gem.name = "moxiesoft_parallel_tests"
11
+ gem.summary = "Run tests / specs / features in parallel"
12
+ gem.email = "grosser.michael@gmail.com"
13
+ gem.homepage = "http://github.com/edebill-moxiesoft/#{gem.name}"
14
+ gem.authors = ['Michael Grosser', 'Eric DeBill']
15
+ gem.add_dependency "parallel"
16
+ end
17
+
18
+ Jeweler::GemcutterTasks.new
19
+ rescue LoadError
20
+ puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install jeweler"
21
+ end
data/Readme.md ADDED
@@ -0,0 +1,156 @@
1
+ Speedup Test::Unit + RSpec + Cucumber by running parallel on multiple CPUs(or cores).
2
+
3
+ Setup for Rails
4
+ ===============
5
+
6
+ ## Install
7
+ ### Rails 3
8
+ As gem
9
+ sudo gem install parallel_tests
10
+ # add to Gemfile
11
+ gem "parallel_tests", :group=>:development
12
+
13
+ OR as plugin
14
+ sudo gem install parallel
15
+ rails plugin install git://github.com/grosser/parallel_tests.git
16
+
17
+ ### Rails 2
18
+
19
+ As gem
20
+ sudo gem install parallel_tests
21
+ # add to config/environments/development.rb
22
+ config.gem "parallel_tests"
23
+ # add to Rakefile
24
+ begin; require 'parallel_tests/tasks'; rescue LoadError; end
25
+
26
+ OR as plugin
27
+
28
+ sudo gem install parallel
29
+ ./script/plugin install git://github.com/grosser/parallel_tests.git
30
+
31
+ ## Setup
32
+ ### 1: Add to `config/database.yml`
33
+ test:
34
+ database: xxx_test<%= ENV['TEST_ENV_NUMBER'] %>
35
+
36
+ ### 2: Create additional database(s)
37
+ rake parallel:create
38
+
39
+ ### 3: Copy development schema (repeat after migrations)
40
+ rake parallel:prepare
41
+
42
+ ### 4: 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 just a subfolder (e.g. use one integration server per subfolder)
53
+ rake parallel:test[models]
54
+ rake parallel:test[something/else]
55
+
56
+ partial paths are OK too...
57
+ rake parallel:test[functional] == rake parallel:test[fun]
58
+
59
+ Example output
60
+ --------------
61
+ 2 processes for 210 specs, ~ 105 specs per process
62
+ ... test output ...
63
+
64
+ Results:
65
+ 877 examples, 0 failures, 11 pending
66
+ 843 examples, 0 failures, 1 pending
67
+
68
+ Took 29.925333 seconds
69
+
70
+ Even process runtimes (for specs only atm)
71
+ -----------------
72
+ Add to your `spec/parallel_spec.opts` (or `spec/spec.opts`) :
73
+ --format ParallelSpecs::SpecRuntimeLogger:tmp/parallel_profile.log
74
+ It will log test runtime and partition the test-load accordingly.
75
+
76
+ Setup for non-rails
77
+ ===================
78
+ sudo gem install parallel_tests
79
+ # go to your project dir
80
+ parallel_test OR parallel_spec OR parallel_cucumber
81
+ # [Optional] use ENV['TEST_ENV_NUMBER'] inside your tests to select separate db/memcache/etc.
82
+
83
+ [optional] Only run selected files & folders:
84
+ parallel_test test/bar test/baz/xxx_text.rb
85
+
86
+ Options are:
87
+ -n [PROCESSES] How many processes to use, default: available CPUs
88
+ -p, --path [PATH] run tests inside this path only
89
+ --no-sort do not sort files before running them
90
+ -m, --multiply-processes [FLOAT] use given number as a multiplier of processes to run
91
+ -r, --root [PATH] execute test commands from this path
92
+ -e, --exec [COMMAND] execute this code parallel and with ENV['TEST_ENV_NUM']
93
+ -o, --test-options '[OPTIONS]' execute test commands with those options
94
+ -t, --type [TYPE] which type of tests to run? test, spec or features
95
+ --non-parallel execute same commands but do not in parallel, needs --exec
96
+ -v, --version Show Version
97
+ -h, --help Show this.
98
+
99
+ You can run any kind of code with -e / --execute
100
+ parallel_test -n 5 -e 'ruby -e "puts %[hello from process #{ENV[:TEST_ENV_NUMBER.to_s].inspect}]"'
101
+ hello from process "2"
102
+ hello from process ""
103
+ hello from process "3"
104
+ hello from process "5"
105
+ hello from process "4"
106
+
107
+ <table>
108
+ <tr><td></td><td>1 Process</td><td>2 Processes</td><td>4 Processes</td></tr>
109
+ <tr><td>RSpec spec-suite</td><td>18s</td><td>14s</td><td>10s</td></tr>
110
+ <tr><td>Rails-ActionPack</td><td>88s</td><td>53s</td><td>44s</td></tr>
111
+ </table>
112
+
113
+ TIPS
114
+ ====
115
+ - [Capybara + Selenium] add to env.rb: `Capybara.server_port = 8888 + ENV['TEST_ENV_NUMBER'].to_i`
116
+ - [RSpec] add a `spec/parallel_spec.opts` to use different options, e.g. no --drb (default: `spec/spec.opts`)
117
+ - [RSpec] if something looks fishy try to delete `script/spec`
118
+ - [RSpec] if `script/spec` is missing parallel:spec uses just `spec` (which solves some issues with double-loaded environment.rb)
119
+ - [RSpec] 'script/spec_server' or [spork](http://github.com/timcharper/spork/tree/master) do not work in parallel
120
+ - [RSpec] `./script/generate rspec` if you are running rspec from gems (this plugin uses script/spec which may fail if rspec files are outdated)
121
+ - [Bundler] if you have a `Gemfile` then `bundle exec` will be used to run tests
122
+ - [Capybara setup](https://github.com/grosser/parallel_tests/wiki)
123
+ - [Sphinx setup](https://github.com/grosser/parallel_tests/wiki)
124
+ - [SQL schema format] use :ruby schema format to get faster parallel:prepare`
125
+ - with zsh this would be `rake "parallel:prepare[3]"`
126
+
127
+ TODO
128
+ ====
129
+ - make jRuby compatible [basics](http://yehudakatz.com/2009/07/01/new-rails-isolation-testing/)
130
+ - make windows compatible
131
+
132
+ Authors
133
+ ====
134
+ inspired by [pivotal labs](http://pivotallabs.com/users/miked/blog/articles/849-parallelize-your-rspec-suite)
135
+
136
+ ### [Contributors](http://github.com/grosser/parallel_tests/contributors)
137
+ - [Charles Finkel](http://charlesfinkel.com/)
138
+ - [Indrek Juhkam](http://urgas.eu)
139
+ - [Jason Morrison](http://jayunit.net)
140
+ - [jinzhu](http://github.com/jinzhu)
141
+ - [Joakim Kolsjö](http://www.rubyblocks.se)
142
+ - [Kevin Scaldeferri](http://kevin.scaldeferri.com/blog/)
143
+ - [Kpumuk](http://kpumuk.info/)
144
+ - [Maksim Horbul](http://github.com/mhorbul)
145
+ - [Pivotal Labs](http://www.pivotallabs.com)
146
+ - [Rohan Deshpande](http://github.com/rdeshpande)
147
+ - [Tchandy](http://thiagopradi.net/)
148
+ - [Terence Lee](http://hone.heroku.com/)
149
+ - [Will Bryant](http://willbryant.net/)
150
+ - [Fred Wu](http://fredwu.me)
151
+ - [xxx](https://github.com/xxx)
152
+ - [Levent Ali](http://purebreeze.com/)
153
+
154
+ [Michael Grosser](http://grosser.it)<br/>
155
+ michael@grosser.it<br/>
156
+ Hereby placed under public domain, do what you want, just do not hold me accountable...
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.4.12
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env ruby
2
+ exec "#{File.join(File.dirname(__FILE__), 'parallel_test')} -t features #{ARGV * ' '}"
data/bin/parallel_spec ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env ruby
2
+ exec "#{File.join(File.dirname(__FILE__), 'parallel_test')} -t spec #{ARGV * ' '}"
data/bin/parallel_test ADDED
@@ -0,0 +1,98 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'optparse'
4
+ require 'parallel'
5
+ raise "please ' gem install parallel '" if Gem::Version.new(Parallel::VERSION) < Gem::Version.new('0.4.2')
6
+ $LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
7
+ require "parallel_tests"
8
+
9
+ options = {}
10
+ OptionParser.new do |opts|
11
+ opts.banner = <<BANNER
12
+ Run all tests in parallel, giving each process ENV['TEST_ENV_NUMBER'] ('', '2', '3', ...)
13
+
14
+ [optional] Only run selected files & folders:
15
+ parallel_test test/bar test/baz/xxx_text.rb
16
+
17
+ Options are:
18
+ BANNER
19
+ opts.on("-n [PROCESSES]", Integer, "How many processes to use, default: available CPUs"){|n| options[:count] = n }
20
+ opts.on("-p", '--path [PATH]', "run tests inside this path only"){|path| options[:path_prefix] = path }
21
+ opts.on("--no-sort", "do not sort files before running them"){ |no_sort| options[:no_sort] = no_sort }
22
+ opts.on("-m [FLOAT]", "--multiply-processes [FLOAT]", Float, "use given number as a multiplier of processes to run"){ |multiply| options[:multiply] = multiply }
23
+ opts.on("-r", '--root [PATH]', "execute test commands from this path"){|path| options[:root] = path }
24
+ opts.on("-e", '--exec [COMMAND]', "execute this code parallel and with ENV['TEST_ENV_NUM']"){|path| options[:execute] = path }
25
+ opts.on("-o", "--test-options '[OPTIONS]'", "execute test commands with those options"){|arg| options[:test_options] = arg }
26
+ opts.on("-t", "--type [TYPE]", "which type of tests to run? test, spec or features"){|type| options[:type] = type }
27
+ opts.on("--non-parallel", "execute same commands but do not in parallel, needs --exec"){|type| options[:non_parallel] = true }
28
+ opts.on('-v', '--version', 'Show Version'){ puts ParallelTests::VERSION; exit}
29
+ opts.on("-h", "--help", "Show this.") { puts opts; exit }
30
+ end.parse!
31
+
32
+ # get files to run from arguments
33
+ options[:files] = ARGV if ARGV.size > 0
34
+
35
+ num_processes = options[:count] || Parallel.processor_count
36
+ num_processes = num_processes * (options[:multiply] || 1)
37
+
38
+ if options[:execute]
39
+ runs = (0...num_processes).to_a
40
+ results = if options[:non_parallel]
41
+ runs.map do |i|
42
+ ParallelTests.execute_command(options[:execute], i)
43
+ end
44
+ else
45
+ Parallel.map(runs, :in_processes => num_processes) do |i|
46
+ ParallelTests.execute_command(options[:execute], i)
47
+ end
48
+ end.flatten
49
+ abort if results.any?{|r| r[:exit_status] != 0 }
50
+ else
51
+ lib, name, task = {
52
+ 'test' => ["tests", "test", "test"],
53
+ 'spec' => ["specs", "spec", "spec"],
54
+ 'features' => ["cucumber", "feature", "features"]
55
+ }[options[:type]||'test']
56
+
57
+ require "parallel_#{lib}"
58
+ klass = eval("Parallel#{lib.capitalize}")
59
+
60
+ start = Time.now
61
+
62
+ options[:path_prefix] = options[:path_prefix] ? options[:path_prefix].split(',') : ['']
63
+ tests_folder = options[:path_prefix].collect do |path|
64
+ tests_folder = File.join(task, path.to_s)
65
+ tests_folder = File.join(options[:root], tests_folder) unless options[:root].to_s.empty?
66
+ tests_folder
67
+ end
68
+ tests_folder = nil if tests_folder.empty?
69
+
70
+ puts "test folders => #{tests_folder}" if tests_folder
71
+
72
+ groups = klass.tests_in_groups(options[:files] || tests_folder, num_processes, :no_sort => options[:no_sort])
73
+ num_processes = groups.size
74
+
75
+ #adjust processes to groups
76
+ abort "no #{name}s found!" if groups.size == 0
77
+
78
+ num_tests = groups.inject(0){|sum,item| sum + item.size }
79
+ puts "#{num_processes} processes for #{num_tests} #{name}s, ~ #{num_tests / groups.size} #{name}s per process"
80
+
81
+ test_results = Parallel.map(groups, :in_processes => num_processes) do |group|
82
+ klass.run_tests(group, groups.index(group), options[:test_options])
83
+ end
84
+
85
+ #parse and print results
86
+ results = klass.find_results(test_results.map{|result| result[:stdout] }*"")
87
+ puts ""
88
+ puts "Results:"
89
+ results.each{|r| puts r }
90
+
91
+ #report total time taken
92
+ puts ""
93
+ puts "Took #{Time.now - start} seconds"
94
+
95
+ #exit with correct status code so rake parallel:test && echo 123 works
96
+ failed = test_results.any?{|result| result[:exit_status] != 0 }
97
+ abort "#{name.capitalize}s Failed" if failed
98
+ end
@@ -0,0 +1,29 @@
1
+ require File.join(File.dirname(__FILE__), 'parallel_tests')
2
+
3
+ class ParallelCucumber < ParallelTests
4
+ def self.run_tests(test_files, process_number, options)
5
+ color = ($stdout.tty? ? 'AUTOTEST=1 ; export AUTOTEST ;' : '')#display color when we are in a terminal
6
+ cmd = "#{color} #{executable} #{options} #{test_files*' '}"
7
+ execute_command(cmd, process_number)
8
+ end
9
+
10
+ def self.executable
11
+ if bundler_enabled?
12
+ "bundle exec cucumber"
13
+ elsif File.file?("script/cucumber")
14
+ "script/cucumber"
15
+ else
16
+ "cucumber"
17
+ end
18
+ end
19
+
20
+ protected
21
+
22
+ def self.test_suffix
23
+ ".feature"
24
+ end
25
+
26
+ def self.line_is_result?(line)
27
+ line =~ /^\d+ (steps|scenarios)/
28
+ end
29
+ end
@@ -0,0 +1,49 @@
1
+ require 'spec/runner/formatter/progress_bar_formatter'
2
+
3
+ class ParallelSpecs::SpecRuntimeLogger < Spec::Runner::Formatter::BaseTextFormatter
4
+ def initialize(options, output)
5
+ if String === output
6
+ FileUtils.mkdir_p(File.dirname(output))
7
+ File.open(output,'w'){|f| f.write ''} # clean the file
8
+ @output = File.open(output, 'a+') #append so that multiple processes can write at once
9
+ else
10
+ @output = output
11
+ end
12
+ @example_times = Hash.new(0)
13
+ end
14
+
15
+ def example_started(*args)
16
+ @time = Time.now
17
+ end
18
+
19
+ def example_passed(example)
20
+ file = example.location.split(':').first
21
+ @example_times[file] += Time.now - @time
22
+ end
23
+
24
+ def start_dump(*args)
25
+ return unless ENV['TEST_ENV_NUMBER'] #only record when running in parallel
26
+ # TODO: Figure out why sometimes time can be less than 0
27
+ @output.puts @example_times.map { |file, time| "#{file}:#{time > 0 ? time : 0}" }
28
+ @output.flush
29
+ end
30
+
31
+ # stubs so that rspec doe not crash
32
+
33
+ def example_pending(*args)
34
+ end
35
+
36
+ def dump_summary(*args)
37
+ end
38
+
39
+ def dump_pending(*args)
40
+ end
41
+
42
+ def dump_failure(*args)
43
+ end
44
+
45
+ #stolen from Rspec
46
+ def close
47
+ @output.close if (IO === @output) & (@output != $stdout)
48
+ end
49
+ end
@@ -0,0 +1,48 @@
1
+ require File.join(File.dirname(__FILE__), 'parallel_tests')
2
+
3
+ class ParallelSpecs < ParallelTests
4
+ def self.run_tests(test_files, process_number, options)
5
+ exe = executable # its expensive with bundler, so do not call it twice
6
+ cmd = "#{color} #{exe} #{options} #{spec_opts(exe)} #{test_files*' '}"
7
+ execute_command(cmd, process_number)
8
+ end
9
+
10
+ def self.executable
11
+ cmd = if File.file?("script/spec")
12
+ "script/spec"
13
+ elsif bundler_enabled?
14
+ cmd = (run("bundle show rspec") =~ %r{/rspec-1[^/]+$} ? "spec" : "rspec")
15
+ "bundle exec #{cmd}"
16
+ else
17
+ %w[spec rspec].detect{|cmd| system "#{cmd} --version > /dev/null 2>&1" }
18
+ end
19
+ cmd or raise("Can't find executables rspec or spec")
20
+ end
21
+
22
+ protected
23
+
24
+ # so it can be stubbed....
25
+ def self.run(cmd)
26
+ `#{cmd}`
27
+ end
28
+
29
+ def self.spec_opts(executable)
30
+ opts = ['spec/parallel_spec.opts', 'spec/spec.opts'].detect{|f| File.file?(f) }
31
+ return unless opts
32
+ if executable =~ /\brspec\b/
33
+ # RSpec2 does not handle -O, so we inline the options
34
+ File.read(opts).tr("\n", ' ')
35
+ else
36
+ "-O #{opts}"
37
+ end
38
+ end
39
+
40
+ #display color when we are in a terminal
41
+ def self.color
42
+ ($stdout.tty? ? 'RSPEC_COLOR=1 ; export RSPEC_COLOR ;' : '')
43
+ end
44
+
45
+ def self.test_suffix
46
+ "_spec.rb"
47
+ end
48
+ end
@@ -0,0 +1,31 @@
1
+ class ParallelTests
2
+ class Grouper
3
+ def self.in_groups(items, num_groups)
4
+ [].tap do |groups|
5
+ while ! items.empty?
6
+ (0...num_groups).map do |group_number|
7
+ groups[group_number] ||= []
8
+ groups[group_number] << items.shift
9
+ end
10
+ end
11
+ end
12
+ end
13
+
14
+ def self.in_even_groups_by_size(items_with_sizes, num_groups)
15
+ items_with_size = smallest_first(items_with_sizes)
16
+ groups = Array.new(num_groups){{:items => [], :size => 0}}
17
+ items_with_size.each do |item, size|
18
+ # always add to smallest group
19
+ smallest = groups.sort_by{|g| g[:size] }.first
20
+ smallest[:items] << item
21
+ smallest[:size] += size
22
+ end
23
+
24
+ groups.map{|g| g[:items] }
25
+ end
26
+
27
+ def self.smallest_first(files)
28
+ files.sort_by{|item, size| size }.reverse
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,10 @@
1
+ # add rake tasks if we are inside Rails
2
+ if defined?(Rails::Railtie)
3
+ class ParallelTests
4
+ class Railtie < ::Rails::Railtie
5
+ rake_tasks do
6
+ load File.expand_path("../../tasks/parallel_tests.rake", __FILE__)
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,80 @@
1
+ namespace :parallel do
2
+ def run_in_parallel(cmd, options)
3
+ count = (options[:count] ? options[:count].to_i : nil)
4
+ executable = File.join(File.dirname(__FILE__), '..', '..', 'bin', 'parallel_test')
5
+ command = "#{executable} --exec '#{cmd}' -n #{count} #{'--non-parallel' if options[:non_parallel]}"
6
+ abort unless system(command)
7
+ end
8
+
9
+ desc "create test databases via db:create --> parallel:create[num_cpus]"
10
+ task :create, :count do |t,args|
11
+ run_in_parallel('rake db:create RAILS_ENV=test', args)
12
+ end
13
+
14
+ desc "drop test databases via db:drop --> parallel:drop[num_cpus]"
15
+ task :drop, :count do |t,args|
16
+ run_in_parallel('rake db:drop RAILS_ENV=test', args)
17
+ end
18
+
19
+ desc "update test databases by dumping and loading --> parallel:prepare[num_cpus]"
20
+ task(:prepare, [:count] => 'db:abort_if_pending_migrations') do |t,args|
21
+ if ActiveRecord::Base.schema_format == :ruby
22
+ # dump then load in parallel
23
+ Rake::Task['db:schema:dump'].invoke
24
+ Rake::Task['parallel:load_schema'].invoke(args[:count])
25
+ else
26
+ # there is no separate dump / load for schema_format :sql -> do it safe and slow
27
+ args = args.to_hash.merge(:non_parallel => true) # normal merge returns nil
28
+ run_in_parallel('rake db:test:prepare --trace', args)
29
+ end
30
+ end
31
+
32
+ # when dumping/resetting takes too long
33
+ desc "update test databases via db:mgrate --> parallel:migrate[num_cpus]"
34
+ task :migrate, :count do |t,args|
35
+ run_in_parallel('rake db:migrate RAILS_ENV=test', args)
36
+ end
37
+
38
+ # just load the schema (good for integration server <-> no development db)
39
+ desc "load dumped schema for test databases via db:schema:load --> parallel:load_schema[num_cpus]"
40
+ task :load_schema, :count do |t,args|
41
+ run_in_parallel('rake db:test:load', args)
42
+ end
43
+
44
+ ['test', 'spec', 'features'].each do |type|
45
+ desc "run #{type} in parallel with parallel:#{type}[num_cpus]"
46
+ task type, :count, :path_prefix, :options do |t,args|
47
+ $LOAD_PATH << File.expand_path(File.join(File.dirname(__FILE__), '..'))
48
+ require "parallel_tests"
49
+ count, prefix, options = ParallelTests.parse_rake_args(args)
50
+ executable = File.join(File.dirname(__FILE__), '..', '..', 'bin', 'parallel_test')
51
+ command = "#{executable} --type #{type} -n #{count} -p '#{prefix}' -r '#{Rails.root}' -o '#{options}'"
52
+ abort unless system(command) # allow to chain tasks e.g. rake parallel:spec parallel:features
53
+ end
54
+ end
55
+ end
56
+
57
+ #backwards compatability
58
+ #spec:parallel:prepare
59
+ #spec:parallel
60
+ #test:parallel
61
+ namespace :spec do
62
+ namespace :parallel do
63
+ task :prepare, :count do |t,args|
64
+ $stderr.puts "WARNING -- Deprecated! use parallel:prepare"
65
+ Rake::Task['parallel:prepare'].invoke(args[:count])
66
+ end
67
+ end
68
+
69
+ task :parallel, :count, :path_prefix do |t,args|
70
+ $stderr.puts "WARNING -- Deprecated! use parallel:spec"
71
+ Rake::Task['parallel:spec'].invoke(args[:count], args[:path_prefix])
72
+ end
73
+ end
74
+
75
+ namespace :test do
76
+ task :parallel, :count, :path_prefix do |t,args|
77
+ $stderr.puts "WARNING -- Deprecated! use parallel:test"
78
+ Rake::Task['parallel:test'].invoke(args[:count], args[:path_prefix])
79
+ end
80
+ end