parallel_tests 1.3.7 → 3.7.3

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.
@@ -1,54 +1,26 @@
1
+ # frozen_string_literal: true
1
2
  require 'parallel_tests/rspec/logger_base'
2
3
  require 'parallel_tests/rspec/runner'
3
4
 
4
5
  class ParallelTests::RSpec::FailuresLogger < ParallelTests::RSpec::LoggerBase
5
- if RSPEC_3
6
- RSpec::Core::Formatters.register self, :dump_failures, :dump_summary
7
- end
8
-
9
- # RSpec 1: does not keep track of failures, so we do
10
- def example_failed(example, *args)
11
- if RSPEC_1
12
- @failed_examples ||= []
13
- @failed_examples << example
14
- else
15
- super
16
- end
17
- end
18
-
19
- if RSPEC_1
20
- def dump_failure(*args)
21
- end
6
+ if RSPEC_2
7
+ def dump_failures(*args); end
22
8
  else
23
- def dump_failures(*args)
24
- end
9
+ RSpec::Core::Formatters.register self, :dump_summary
25
10
  end
26
11
 
27
12
  def dump_summary(*args)
28
13
  lock_output do
29
- if RSPEC_1
30
- dump_commands_to_rerun_failed_examples_rspec_1
31
- elsif RSPEC_3
14
+ if RSPEC_2
15
+ dump_commands_to_rerun_failed_examples
16
+ else
32
17
  notification = args.first
33
18
  unless notification.failed_examples.empty?
34
19
  colorizer = ::RSpec::Core::Formatters::ConsoleCodes
35
20
  output.puts notification.colorized_rerun_commands(colorizer)
36
21
  end
37
- else
38
- dump_commands_to_rerun_failed_examples
39
22
  end
40
23
  end
41
24
  @output.flush
42
25
  end
43
-
44
- private
45
-
46
- def dump_commands_to_rerun_failed_examples_rspec_1
47
- (@failed_examples||[]).each do |example|
48
- file, line = example.location.to_s.split(':')
49
- next unless file and line
50
- file.gsub!(%r(^.*?/spec/), './spec/')
51
- @output.puts "#{ParallelTests::RSpec::Runner.send(:executable)} #{file}:#{line} # #{example.description}"
52
- end
53
- end
54
26
  end
@@ -1,47 +1,40 @@
1
+ # frozen_string_literal: true
1
2
  module ParallelTests
2
3
  module RSpec
3
4
  end
4
5
  end
5
6
 
6
- begin
7
- require 'rspec/core/formatters/base_text_formatter'
8
- base = RSpec::Core::Formatters::BaseTextFormatter
9
- rescue LoadError
10
- require 'spec/runner/formatter/base_text_formatter'
11
- base = Spec::Runner::Formatter::BaseTextFormatter
12
- end
13
-
14
- ParallelTests::RSpec::LoggerBaseBase = base
7
+ require 'rspec/core/formatters/base_text_formatter'
15
8
 
16
- class ParallelTests::RSpec::LoggerBase < ParallelTests::RSpec::LoggerBaseBase
17
- RSPEC_1 = !defined?(RSpec::Core::Formatters::BaseTextFormatter) # do not test for Spec, this will trigger deprecation warning in rspec 2
18
- RSPEC_3 = !RSPEC_1 && RSpec::Core::Version::STRING.start_with?('3')
9
+ class ParallelTests::RSpec::LoggerBase < RSpec::Core::Formatters::BaseTextFormatter
10
+ RSPEC_2 = RSpec::Core::Version::STRING.start_with?('2')
19
11
 
20
12
  def initialize(*args)
21
13
  super
22
14
 
23
- @output ||= args[1] || args[0] # rspec 1 has output as second argument
15
+ @output ||= args[0]
24
16
 
25
- if String === @output # a path ?
17
+ case @output
18
+ when String # a path ?
26
19
  FileUtils.mkdir_p(File.dirname(@output))
27
- File.open(@output, 'w'){} # overwrite previous results
20
+ File.open(@output, 'w') {} # overwrite previous results
28
21
  @output = File.open(@output, 'a')
29
- elsif File === @output # close and restart in append mode
22
+ when File # close and restart in append mode
30
23
  @output.close
31
24
  @output = File.open(@output.path, 'a')
32
25
  end
33
26
  end
34
27
 
35
- #stolen from Rspec
36
- def close(*args)
37
- @output.close if (IO === @output) & (@output != $stdout)
28
+ # stolen from Rspec
29
+ def close(*)
30
+ @output.close if (IO === @output) & (@output != $stdout)
38
31
  end
39
32
 
40
33
  protected
41
34
 
42
35
  # do not let multiple processes get in each others way
43
36
  def lock_output
44
- if File === @output
37
+ if @output.is_a?(File)
45
38
  begin
46
39
  @output.flock File::LOCK_EX
47
40
  yield
@@ -1,38 +1,33 @@
1
+ # frozen_string_literal: true
1
2
  require "parallel_tests/test/runner"
2
3
 
3
4
  module ParallelTests
4
5
  module RSpec
5
6
  class Runner < ParallelTests::Test::Runner
6
7
  DEV_NULL = (WINDOWS ? "NUL" : "/dev/null")
7
- NAME = 'RSpec'
8
-
9
8
  class << self
10
9
  def run_tests(test_files, process_number, num_processes, options)
11
10
  exe = executable # expensive, so we cache
12
- version = (exe =~ /\brspec\b/ ? 2 : 1)
13
- cmd = [exe, options[:test_options], (rspec_2_color if version == 2), spec_opts, *test_files].compact.join(" ")
14
- options = options.merge(:env => rspec_1_color) if version == 1
11
+ cmd = [exe, options[:test_options], color, spec_opts, *test_files].compact.join(" ")
15
12
  execute_command(cmd, process_number, num_processes, options)
16
13
  end
17
14
 
18
15
  def determine_executable
19
- cmd = case
20
- when File.exist?("bin/rspec")
21
- WINDOWS ? "ruby bin/rspec" : "bin/rspec"
22
- when File.file?("script/spec")
23
- "script/spec"
24
- when ParallelTests.bundler_enabled?
25
- cmd = (run("bundle show rspec-core") =~ %r{Could not find gem.*} ? "spec" : "rspec")
26
- "bundle exec #{cmd}"
16
+ if File.exist?("bin/rspec")
17
+ ParallelTests.with_ruby_binary("bin/rspec")
18
+ elsif ParallelTests.bundler_enabled?
19
+ "bundle exec rspec"
27
20
  else
28
- %w[spec rspec].detect{|cmd| system "#{cmd} --version > #{DEV_NULL} 2>&1" }
21
+ "rspec"
29
22
  end
30
-
31
- cmd or raise("Can't find executables rspec or spec")
32
23
  end
33
24
 
34
25
  def runtime_log
35
- 'tmp/parallel_runtime_rspec.log'
26
+ "tmp/parallel_runtime_rspec.log"
27
+ end
28
+
29
+ def default_test_folder
30
+ "spec"
36
31
  end
37
32
 
38
33
  def test_file_name
@@ -43,6 +38,37 @@ module ParallelTests
43
38
  /_spec\.rb$/
44
39
  end
45
40
 
41
+ def line_is_result?(line)
42
+ line =~ /\d+ examples?, \d+ failures?/
43
+ end
44
+
45
+ # remove old seed and add new seed
46
+ # --seed 1234
47
+ # --order rand
48
+ # --order rand:1234
49
+ # --order random:1234
50
+ def command_with_seed(cmd, seed)
51
+ clean = cmd.sub(/\s--(seed\s+\d+|order\s+rand(om)?(:\d+)?)\b/, '')
52
+ "#{clean} --seed #{seed}"
53
+ end
54
+
55
+ # Summarize results from threads and colorize results based on failure and pending counts.
56
+ #
57
+ def summarize_results(results)
58
+ text = super
59
+ return text unless $stdout.tty?
60
+ sums = sum_up_results(results)
61
+ color =
62
+ if sums['failure'] > 0
63
+ 31 # red
64
+ elsif sums['pending'] > 0
65
+ 33 # yellow
66
+ else
67
+ 32 # green
68
+ end
69
+ "\e[#{color}m#{text}\e[0m"
70
+ end
71
+
46
72
  private
47
73
 
48
74
  # so it can be stubbed....
@@ -50,20 +76,12 @@ module ParallelTests
50
76
  `#{cmd}`
51
77
  end
52
78
 
53
- def rspec_1_color
54
- if $stdout.tty?
55
- {'RSPEC_COLOR' => "1"}
56
- else
57
- {}
58
- end
59
- end
60
-
61
- def rspec_2_color
79
+ def color
62
80
  '--color --tty' if $stdout.tty?
63
81
  end
64
82
 
65
83
  def spec_opts
66
- options_file = ['.rspec_parallel', 'spec/parallel_spec.opts', 'spec/spec.opts'].detect{|f| File.file?(f) }
84
+ options_file = ['.rspec_parallel', 'spec/parallel_spec.opts', 'spec/spec.opts'].detect { |f| File.file?(f) }
67
85
  return unless options_file
68
86
  "-O #{options_file}"
69
87
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'parallel_tests'
2
3
  require 'parallel_tests/rspec/logger_base'
3
4
 
@@ -5,52 +6,39 @@ class ParallelTests::RSpec::RuntimeLogger < ParallelTests::RSpec::LoggerBase
5
6
  def initialize(*args)
6
7
  super
7
8
  @example_times = Hash.new(0)
8
- @group_nesting = 0 unless RSPEC_1
9
+ @group_nesting = 0
9
10
  end
10
11
 
11
- if RSPEC_3
12
- RSpec::Core::Formatters.register self, :example_group_started, :example_group_finished, :start_dump
12
+ RSpec::Core::Formatters.register self, :example_group_started, :example_group_finished, :start_dump unless RSPEC_2
13
+
14
+ def example_group_started(example_group)
15
+ @time = ParallelTests.now if @group_nesting == 0
16
+ @group_nesting += 1
17
+ super
13
18
  end
14
19
 
15
- if RSPEC_1
16
- def example_started(*args)
17
- @time = ParallelTests.now
18
- super
20
+ def example_group_finished(notification)
21
+ @group_nesting -= 1
22
+ if @group_nesting == 0
23
+ path = (RSPEC_2 ? notification.file_path : notification.group.file_path)
24
+ @example_times[path] += ParallelTests.now - @time
19
25
  end
26
+ super if defined?(super)
27
+ end
20
28
 
21
- def example_passed(example)
22
- file = example.location.split(':').first
23
- @example_times[file] += ParallelTests.now - @time
24
- super
25
- end
26
- else
27
- def example_group_started(example_group)
28
- @time = ParallelTests.now if @group_nesting == 0
29
- @group_nesting += 1
30
- super
31
- end
29
+ def dump_summary(*); end
32
30
 
33
- def example_group_finished(notification)
34
- @group_nesting -= 1
35
- if @group_nesting == 0
36
- path = (RSPEC_3 ? notification.group.file_path : notification.file_path)
37
- @example_times[path] += ParallelTests.now - @time
38
- end
39
- super if defined?(super)
40
- end
41
- end
31
+ def dump_failures(*); end
32
+
33
+ def dump_failure(*); end
42
34
 
43
- def dump_summary(*args);end
44
- def dump_failures(*args);end
45
- def dump_failure(*args);end
46
- def dump_pending(*args);end
35
+ def dump_pending(*); end
47
36
 
48
- def start_dump(*args)
49
- return unless ENV['TEST_ENV_NUMBER'] #only record when running in parallel
50
- # TODO: Figure out why sometimes time can be less than 0
37
+ def start_dump(*)
38
+ return unless ENV['TEST_ENV_NUMBER'] # only record when running in parallel
51
39
  lock_output do
52
40
  @example_times.each do |file, time|
53
- relative_path = file.sub(/^#{Regexp.escape Dir.pwd}\//,'').sub(/^\.\//, "")
41
+ relative_path = file.sub(%r{^#{Regexp.escape Dir.pwd}/}, '').sub(%r{^\./}, "")
54
42
  @output.puts "#{relative_path}:#{time > 0 ? time : 0}"
55
43
  end
56
44
  end
@@ -1,19 +1,11 @@
1
+ # frozen_string_literal: true
1
2
  require 'parallel_tests/rspec/failures_logger'
2
3
 
3
4
  class ParallelTests::RSpec::SummaryLogger < ParallelTests::RSpec::LoggerBase
4
- if RSPEC_3
5
- RSpec::Core::Formatters.register self, :dump_failures
6
- end
5
+ RSpec::Core::Formatters.register self, :dump_failures unless RSPEC_2
7
6
 
8
- if RSPEC_1
9
- def dump_failure(*args)
10
- lock_output { super }
11
- @output.flush
12
- end
13
- else
14
- def dump_failures(*args)
15
- lock_output { super }
16
- @output.flush
17
- end
7
+ def dump_failures(*args)
8
+ lock_output { super }
9
+ @output.flush
18
10
  end
19
11
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "parallel_tests/gherkin/runner"
2
3
 
3
4
  module ParallelTests
@@ -8,11 +9,14 @@ module ParallelTests
8
9
  'spinach'
9
10
  end
10
11
 
12
+ def default_test_folder
13
+ 'features'
14
+ end
15
+
11
16
  def runtime_logging
12
- #Not Yet Supported
17
+ # Not Yet Supported
13
18
  ""
14
19
  end
15
-
16
20
  end
17
21
  end
18
22
  end
@@ -1,21 +1,45 @@
1
+ # frozen_string_literal: true
1
2
  require 'rake'
3
+ require 'shellwords'
2
4
 
3
5
  module ParallelTests
4
6
  module Tasks
5
7
  class << self
6
8
  def rails_env
7
- ENV['RAILS_ENV'] || 'test'
9
+ 'test'
8
10
  end
9
11
 
10
- def run_in_parallel(cmd, options={})
12
+ def rake_bin
13
+ # Prevent 'Exec format error' Errno::ENOEXEC on Windows
14
+ return "rake" if RUBY_PLATFORM =~ /mswin|mingw|cygwin/
15
+ binstub_path = File.join('bin', 'rake')
16
+ return binstub_path if File.exist?(binstub_path)
17
+ "rake"
18
+ end
19
+
20
+ def load_lib
21
+ $LOAD_PATH << File.expand_path(File.join(File.dirname(__FILE__), '..'))
22
+ require "parallel_tests"
23
+ end
24
+
25
+ def purge_before_load
26
+ if Gem::Version.new(Rails.version) > Gem::Version.new('4.2.0')
27
+ Rake::Task.task_defined?('db:purge') ? 'db:purge' : 'app:db:purge'
28
+ end
29
+ end
30
+
31
+ def run_in_parallel(cmd, options = {})
32
+ load_lib
11
33
  count = " -n #{options[:count]}" unless options[:count].to_s.empty?
12
- executable = File.expand_path("../../../bin/parallel_test", __FILE__)
13
- command = "#{executable} --exec '#{cmd}'#{count}#{' --non-parallel' if options[:non_parallel]}"
34
+ # Using the relative path to find the binary allow to run a specific version of it
35
+ executable = File.expand_path('../../bin/parallel_test', __dir__)
36
+ non_parallel = (options[:non_parallel] ? ' --non-parallel' : '')
37
+ command = "#{ParallelTests.with_ruby_binary(Shellwords.escape(executable))} --exec '#{cmd}'#{count}#{non_parallel}"
14
38
  abort unless system(command)
15
39
  end
16
40
 
17
41
  # this is a crazy-complex solution for a very simple problem:
18
- # removing certain lines from the output without chaning the exit-status
42
+ # removing certain lines from the output without changing the exit-status
19
43
  # normally I'd not do this, but it has been lots of fun and a great learning experience :)
20
44
  #
21
45
  # - sed does not support | without -r
@@ -28,17 +52,21 @@ module ParallelTests
28
52
  # - simple system "set -o pipefail" returns nil even though set -o pipefail exists with 0
29
53
  def suppress_output(command, ignore_regex)
30
54
  activate_pipefail = "set -o pipefail"
31
- remove_ignored_lines = %Q{(grep -v "#{ignore_regex}" || test 1)}
55
+ remove_ignored_lines = %{(grep -v "#{ignore_regex}" || test 1)}
32
56
 
33
57
  if File.executable?('/bin/bash') && system('/bin/bash', '-c', "#{activate_pipefail} 2>/dev/null && test 1")
34
58
  # We need to shell escape single quotes (' becomes '"'"') because
35
59
  # run_in_parallel wraps command in single quotes
36
- %Q{/bin/bash -c '"'"'#{activate_pipefail} && (#{command}) | #{remove_ignored_lines}'"'"'}
60
+ %{/bin/bash -c '"'"'#{activate_pipefail} && (#{command}) | #{remove_ignored_lines}'"'"'}
37
61
  else
38
62
  command
39
63
  end
40
64
  end
41
65
 
66
+ def suppress_schema_load_output(command)
67
+ ParallelTests::Tasks.suppress_output(command, "^ ->\\|^-- ")
68
+ end
69
+
42
70
  def check_for_pending_migrations
43
71
  ["db:abort_if_pending_migrations", "app:db:abort_if_pending_migrations"].each do |abort_migrations|
44
72
  if Rake::Task.task_defined?(abort_migrations)
@@ -48,109 +76,147 @@ module ParallelTests
48
76
  end
49
77
  end
50
78
 
51
- # parallel:spec[:count, :pattern, :options]
79
+ # parallel:spec[:count, :pattern, :options, :pass_through]
52
80
  def parse_args(args)
53
81
  # order as given by user
54
- args = [args[:count], args[:pattern], args[:options]]
82
+ args = [args[:count], args[:pattern], args[:options], args[:pass_through]]
55
83
 
56
84
  # count given or empty ?
57
85
  # parallel:spec[2,models,options]
58
86
  # parallel:spec[,models,options]
59
87
  count = args.shift if args.first.to_s =~ /^\d*$/
60
- num_processes = count.to_i unless count.to_s.empty?
88
+ num_processes = (count.to_s.empty? ? nil : Integer(count))
61
89
  pattern = args.shift
62
90
  options = args.shift
91
+ pass_through = args.shift
63
92
 
64
- [num_processes, pattern.to_s, options.to_s]
93
+ [num_processes, pattern.to_s, options.to_s, pass_through.to_s]
65
94
  end
66
95
  end
67
96
  end
68
97
  end
69
98
 
70
99
  namespace :parallel do
71
- desc "create test databases via db:create --> parallel:create[num_cpus]"
72
- task :create, :count do |t,args|
73
- ParallelTests::Tasks.run_in_parallel("rake db:create RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args)
100
+ desc "Setup test databases via db:setup --> parallel:setup[num_cpus]"
101
+ task :setup, :count do |_, args|
102
+ command = "#{ParallelTests::Tasks.rake_bin} db:setup RAILS_ENV=#{ParallelTests::Tasks.rails_env}"
103
+ ParallelTests::Tasks.run_in_parallel(ParallelTests::Tasks.suppress_schema_load_output(command), args)
104
+ end
105
+
106
+ desc "Create test databases via db:create --> parallel:create[num_cpus]"
107
+ task :create, :count do |_, args|
108
+ ParallelTests::Tasks.run_in_parallel(
109
+ "#{ParallelTests::Tasks.rake_bin} db:create RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args
110
+ )
74
111
  end
75
112
 
76
- desc "drop test databases via db:drop --> parallel:drop[num_cpus]"
77
- task :drop, :count do |t,args|
78
- ParallelTests::Tasks.run_in_parallel("rake db:drop RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args)
113
+ desc "Drop test databases via db:drop --> parallel:drop[num_cpus]"
114
+ task :drop, :count do |_, args|
115
+ ParallelTests::Tasks.run_in_parallel(
116
+ "#{ParallelTests::Tasks.rake_bin} db:drop RAILS_ENV=#{ParallelTests::Tasks.rails_env} " \
117
+ "DISABLE_DATABASE_ENVIRONMENT_CHECK=1", args
118
+ )
79
119
  end
80
120
 
81
- desc "update test databases by dumping and loading --> parallel:prepare[num_cpus]"
82
- task(:prepare, [:count]) do |t,args|
121
+ desc "Update test databases by dumping and loading --> parallel:prepare[num_cpus]"
122
+ task(:prepare, [:count]) do |_, args|
83
123
  ParallelTests::Tasks.check_for_pending_migrations
84
- if defined?(ActiveRecord) && ActiveRecord::Base.schema_format == :ruby
85
- # dump then load in parallel
86
- Rake::Task['db:schema:dump'].invoke
87
- Rake::Task['parallel:load_schema'].invoke(args[:count])
124
+ if defined?(ActiveRecord::Base) && [:ruby, :sql].include?(ActiveRecord::Base.schema_format)
125
+ # fast: dump once, load in parallel
126
+ type =
127
+ if Gem::Version.new(Rails.version) >= Gem::Version.new('6.1.0')
128
+ "schema"
129
+ else
130
+ ActiveRecord::Base.schema_format == :ruby ? "schema" : "structure"
131
+ end
132
+
133
+ Rake::Task["db:#{type}:dump"].invoke
134
+
135
+ # remove database connection to prevent "database is being accessed by other users"
136
+ ActiveRecord::Base.remove_connection if ActiveRecord::Base.configurations.any?
137
+
138
+ Rake::Task["parallel:load_#{type}"].invoke(args[:count])
88
139
  else
89
- # there is no separate dump / load for schema_format :sql -> do it safe and slow
90
- args = args.to_hash.merge(:non_parallel => true) # normal merge returns nil
91
- taskname = Rake::Task.task_defined?('db:test:prepare') ? 'db:test:prepare' : 'app:db:test:prepare'
92
- ParallelTests::Tasks.run_in_parallel("rake #{taskname}", args)
140
+ # slow: dump and load in in serial
141
+ args = args.to_hash.merge(non_parallel: true) # normal merge returns nil
142
+ task_name = Rake::Task.task_defined?('db:test:prepare') ? 'db:test:prepare' : 'app:db:test:prepare'
143
+ ParallelTests::Tasks.run_in_parallel("#{ParallelTests::Tasks.rake_bin} #{task_name}", args)
144
+ next
93
145
  end
94
146
  end
95
147
 
96
148
  # when dumping/resetting takes too long
97
- desc "update test databases via db:migrate --> parallel:migrate[num_cpus]"
98
- task :migrate, :count do |t,args|
99
- ParallelTests::Tasks.run_in_parallel("rake db:migrate RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args)
149
+ desc "Update test databases via db:migrate --> parallel:migrate[num_cpus]"
150
+ task :migrate, :count do |_, args|
151
+ ParallelTests::Tasks.run_in_parallel(
152
+ "#{ParallelTests::Tasks.rake_bin} db:migrate RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args
153
+ )
154
+ end
155
+
156
+ desc "Rollback test databases via db:rollback --> parallel:rollback[num_cpus]"
157
+ task :rollback, :count do |_, args|
158
+ ParallelTests::Tasks.run_in_parallel(
159
+ "#{ParallelTests::Tasks.rake_bin} db:rollback RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args
160
+ )
100
161
  end
101
162
 
102
163
  # just load the schema (good for integration server <-> no development db)
103
- desc "load dumped schema for test databases via db:schema:load --> parallel:load_schema[num_cpus]"
104
- task :load_schema, :count do |t,args|
105
- command = "rake db:schema:load RAILS_ENV=#{ParallelTests::Tasks.rails_env}"
106
- ParallelTests::Tasks.run_in_parallel(ParallelTests::Tasks.suppress_output(command, "^ ->\\|^-- "), args)
164
+ desc "Load dumped schema for test databases via db:schema:load --> parallel:load_schema[num_cpus]"
165
+ task :load_schema, :count do |_, args|
166
+ command = "#{ParallelTests::Tasks.rake_bin} #{ParallelTests::Tasks.purge_before_load} " \
167
+ "db:schema:load RAILS_ENV=#{ParallelTests::Tasks.rails_env} DISABLE_DATABASE_ENVIRONMENT_CHECK=1"
168
+ ParallelTests::Tasks.run_in_parallel(ParallelTests::Tasks.suppress_schema_load_output(command), args)
107
169
  end
108
170
 
109
171
  # load the structure from the structure.sql file
110
- desc "load structure for test databases via db:structure:load --> parallel:load_structure[num_cpus]"
111
- task :load_structure, :count do |t,args|
112
- ParallelTests::Tasks.run_in_parallel("rake db:structure:load RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args)
172
+ # (faster for rails < 6.1, deprecated after and only configured by `ActiveRecord::Base.schema_format`)
173
+ desc "Load structure for test databases via db:schema:load --> parallel:load_structure[num_cpus]"
174
+ task :load_structure, :count do |_, args|
175
+ ParallelTests::Tasks.run_in_parallel(
176
+ "#{ParallelTests::Tasks.rake_bin} #{ParallelTests::Tasks.purge_before_load} " \
177
+ "db:structure:load RAILS_ENV=#{ParallelTests::Tasks.rails_env} DISABLE_DATABASE_ENVIRONMENT_CHECK=1", args
178
+ )
113
179
  end
114
180
 
115
- desc "load the seed data from db/seeds.rb via db:seed --> parallel:seed[num_cpus]"
116
- task :seed, :count do |t,args|
117
- ParallelTests::Tasks.run_in_parallel("rake db:seed RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args)
181
+ desc "Load the seed data from db/seeds.rb via db:seed --> parallel:seed[num_cpus]"
182
+ task :seed, :count do |_, args|
183
+ ParallelTests::Tasks.run_in_parallel(
184
+ "#{ParallelTests::Tasks.rake_bin} db:seed RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args
185
+ )
118
186
  end
119
187
 
120
- desc "launch given rake command in parallel"
121
- task :rake, :command do |t, args|
122
- ParallelTests::Tasks.run_in_parallel("RAILS_ENV=#{ParallelTests::Tasks.rails_env} rake #{args.command}")
188
+ desc "Launch given rake command in parallel"
189
+ task :rake, :command, :count do |_, args|
190
+ ParallelTests::Tasks.run_in_parallel(
191
+ "RAILS_ENV=#{ParallelTests::Tasks.rails_env} #{ParallelTests::Tasks.rake_bin} " \
192
+ "#{args.command}", args
193
+ )
123
194
  end
124
195
 
125
196
  ['test', 'spec', 'features', 'features-spinach'].each do |type|
126
- desc "run #{type} in parallel with parallel:#{type}[num_cpus]"
127
- task type, [:count, :pattern, :options] do |t, args|
197
+ desc "Run #{type} in parallel with parallel:#{type}[num_cpus]"
198
+ task type, [:count, :pattern, :options, :pass_through] do |_t, args|
128
199
  ParallelTests::Tasks.check_for_pending_migrations
200
+ ParallelTests::Tasks.load_lib
129
201
 
130
- $LOAD_PATH << File.expand_path(File.join(File.dirname(__FILE__), '..'))
131
- require "parallel_tests"
132
-
133
- count, pattern, options = ParallelTests::Tasks.parse_args(args)
202
+ count, pattern, options, pass_through = ParallelTests::Tasks.parse_args(args)
134
203
  test_framework = {
135
204
  'spec' => 'rspec',
136
205
  'test' => 'test',
137
206
  'features' => 'cucumber',
138
- 'features-spinach' => 'spinach',
207
+ 'features-spinach' => 'spinach'
139
208
  }[type]
140
209
 
141
- if test_framework == 'spinach'
142
- type = 'features'
143
- end
210
+ type = 'features' if test_framework == 'spinach'
211
+ # Using the relative path to find the binary allow to run a specific version of it
144
212
  executable = File.join(File.dirname(__FILE__), '..', '..', 'bin', 'parallel_test')
145
213
 
146
- command = "#{executable} #{type} --type #{test_framework} " \
214
+ command = "#{ParallelTests.with_ruby_binary(Shellwords.escape(executable))} #{type} " \
215
+ "--type #{test_framework} " \
147
216
  "-n #{count} " \
148
217
  "--pattern '#{pattern}' " \
149
- "--test-options '#{options}'"
150
- if ParallelTests::WINDOWS
151
- ruby_binary = File.join(RbConfig::CONFIG['bindir'], RbConfig::CONFIG['ruby_install_name'])
152
- command = "#{ruby_binary} #{command}"
153
- end
218
+ "--test-options '#{options}' " \
219
+ "#{pass_through}"
154
220
  abort unless system(command) # allow to chain tasks e.g. rake parallel:spec parallel:features
155
221
  end
156
222
  end