mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Disable parallel testing when running individual files
Setting up the parallel workers could be an overhead when running individual files. This patch disables that process in case the number of files to run is less than one. Results running a sample file: Before: ``` actionpack $ bin/test test/controller/parameters/accessors_test.rb Run options: --seed 48261 ........................................................................ Finished in 0.211923s, 339.7460 runs/s, 552.0873 assertions/s. 72 runs, 117 assertions, 0 failures, 0 errors, 0 skips ``` After ``` actionpack $ bin/test test/controller/parameters/accessors_test.rb Run options: --seed 5461 ........................................................................ Finished in 0.008411s, 8560.2189 runs/s, 13910.3557 assertions/s. 72 runs, 117 assertions, 0 failures, 0 errors, 0 skips ```
This commit is contained in:
parent
168ddaa08a
commit
2327ebfdc6
5 changed files with 112 additions and 6 deletions
|
@ -1,3 +1,9 @@
|
||||||
|
* Tests parallelization is now disabled when running individual files to prevent the setup overhead.
|
||||||
|
|
||||||
|
It can still be enforced if the environment variable `PARALLEL_WORKERS` is present and set to a value greater than 1.
|
||||||
|
|
||||||
|
*Ricardo Díaz*
|
||||||
|
|
||||||
* Fix proxying keyword arguments in `ActiveSupport::CurrentAttributes`.
|
* Fix proxying keyword arguments in `ActiveSupport::CurrentAttributes`.
|
||||||
|
|
||||||
*Marcin Kołodziej*
|
*Marcin Kołodziej*
|
||||||
|
|
|
@ -87,6 +87,11 @@ module ActiveSupport
|
||||||
end
|
end
|
||||||
|
|
||||||
cattr_accessor :test_order # :nodoc:
|
cattr_accessor :test_order # :nodoc:
|
||||||
|
cattr_accessor :test_parallelization_disabled, default: false # :nodoc:
|
||||||
|
|
||||||
|
def self.disable_test_parallelization!
|
||||||
|
self.test_parallelization_disabled = true unless ENV["PARALLEL_WORKERS"]
|
||||||
|
end
|
||||||
|
|
||||||
def self.to_time_preserves_timezone
|
def self.to_time_preserves_timezone
|
||||||
DateAndTime::Compatibility.preserve_timezone
|
DateAndTime::Compatibility.preserve_timezone
|
||||||
|
|
|
@ -75,7 +75,7 @@ module ActiveSupport
|
||||||
workers = Concurrent.physical_processor_count if workers == :number_of_processors
|
workers = Concurrent.physical_processor_count if workers == :number_of_processors
|
||||||
workers = ENV["PARALLEL_WORKERS"].to_i if ENV["PARALLEL_WORKERS"]
|
workers = ENV["PARALLEL_WORKERS"].to_i if ENV["PARALLEL_WORKERS"]
|
||||||
|
|
||||||
return if workers <= 1
|
return if workers <= 1 || ActiveSupport.test_parallelization_disabled
|
||||||
|
|
||||||
executor = case with
|
executor = case with
|
||||||
when :processes
|
when :processes
|
||||||
|
@ -91,6 +91,12 @@ module ActiveSupport
|
||||||
Minitest.parallel_executor = executor
|
Minitest.parallel_executor = executor
|
||||||
|
|
||||||
parallelize_me!
|
parallelize_me!
|
||||||
|
|
||||||
|
# `Minitest::Test.parallelize_me!` will try to change `test_order` to return
|
||||||
|
# `:parallel`. However, since `ActiveSupport::TestCase` is already overriding it,
|
||||||
|
# in some inheritance situations, it will have precedence over the `Minitest` one.
|
||||||
|
# For this reason, it needs to be updated by hand.
|
||||||
|
self.test_order = :parallel
|
||||||
end
|
end
|
||||||
|
|
||||||
# Set up hook for parallel testing. This can be used if you have multiple
|
# Set up hook for parallel testing. This can be used if you have multiple
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
require "shellwords"
|
require "shellwords"
|
||||||
require "method_source"
|
require "method_source"
|
||||||
require "rake/file_list"
|
require "rake/file_list"
|
||||||
|
require "active_support"
|
||||||
require "active_support/core_ext/module/attribute_accessors"
|
require "active_support/core_ext/module/attribute_accessors"
|
||||||
|
|
||||||
module Rails
|
module Rails
|
||||||
|
@ -46,7 +47,8 @@ module Rails
|
||||||
|
|
||||||
tests = Rake::FileList[patterns.any? ? patterns : default_test_glob]
|
tests = Rake::FileList[patterns.any? ? patterns : default_test_glob]
|
||||||
tests.exclude(default_test_exclude_glob) if patterns.empty?
|
tests.exclude(default_test_exclude_glob) if patterns.empty?
|
||||||
|
# Disable parallel testing if there's only one test file to run.
|
||||||
|
ActiveSupport.disable_test_parallelization! if tests.size <= 1
|
||||||
tests.to_a.each { |path| require File.expand_path(path) }
|
tests.to_a.each { |path| require File.expand_path(path) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -539,6 +539,76 @@ module ApplicationTests
|
||||||
assert_no_match "create_table(:users)", output
|
assert_no_match "create_table(:users)", output
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_parallel_is_disabled_when_single_file_is_run
|
||||||
|
exercise_parallelization_regardless_of_machine_core_count(with: :processes, force: false)
|
||||||
|
|
||||||
|
file_name = app_file "test/unit/parallel_test.rb", <<-RUBY
|
||||||
|
require "test_helper"
|
||||||
|
|
||||||
|
class ParallelTest < ActiveSupport::TestCase
|
||||||
|
def test_verify_test_order
|
||||||
|
puts "Test order: \#{self.class.test_order}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
|
||||||
|
output = run_test_command(file_name)
|
||||||
|
|
||||||
|
assert_match "Test order: random", output
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_parallel_is_enabled_when_multiple_files_are_run
|
||||||
|
exercise_parallelization_regardless_of_machine_core_count(with: :processes, force: false)
|
||||||
|
|
||||||
|
file_1 = app_file "test/unit/parallel_test_first.rb", <<-RUBY
|
||||||
|
require "test_helper"
|
||||||
|
|
||||||
|
class ParallelTestFirst < ActiveSupport::TestCase
|
||||||
|
def test_verify_test_order
|
||||||
|
puts "Test order (file 1): \#{self.class.test_order}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
|
||||||
|
file_2 = app_file "test/unit/parallel_test_second.rb", <<-RUBY
|
||||||
|
require "test_helper"
|
||||||
|
|
||||||
|
class ParallelTestSecond < ActiveSupport::TestCase
|
||||||
|
def test_verify_test_order
|
||||||
|
puts "Test order (file 2): \#{self.class.test_order}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
|
||||||
|
output = run_test_command([file_1, file_2].join(" "))
|
||||||
|
|
||||||
|
assert_match "Test order (file 1): parallel", output
|
||||||
|
assert_match "Test order (file 2): parallel", output
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_parallel_is_enabled_when_PARALLEL_WORKERS_is_set
|
||||||
|
@old = ENV["PARALLEL_WORKERS"]
|
||||||
|
ENV["PARALLEL_WORKERS"] = "5"
|
||||||
|
|
||||||
|
exercise_parallelization_regardless_of_machine_core_count(with: :processes, force: false)
|
||||||
|
|
||||||
|
file_name = app_file "test/unit/parallel_test.rb", <<-RUBY
|
||||||
|
require "test_helper"
|
||||||
|
|
||||||
|
class ParallelTest < ActiveSupport::TestCase
|
||||||
|
def test_verify_test_order
|
||||||
|
puts "Test order: \#{self.class.test_order}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
|
||||||
|
output = run_test_command(file_name)
|
||||||
|
|
||||||
|
assert_match "Test order: parallel", output
|
||||||
|
ensure
|
||||||
|
ENV["PARALLEL_WORKERS"] = @old
|
||||||
|
end
|
||||||
|
|
||||||
def test_run_in_parallel_with_process_worker_crash
|
def test_run_in_parallel_with_process_worker_crash
|
||||||
exercise_parallelization_regardless_of_machine_core_count(with: :processes)
|
exercise_parallelization_regardless_of_machine_core_count(with: :processes)
|
||||||
|
|
||||||
|
@ -1039,11 +1109,28 @@ module ApplicationTests
|
||||||
RUBY
|
RUBY
|
||||||
end
|
end
|
||||||
|
|
||||||
def exercise_parallelization_regardless_of_machine_core_count(with:)
|
def exercise_parallelization_regardless_of_machine_core_count(with:, force: true)
|
||||||
|
file_content = ERB.new(<<-ERB, trim_mode: "-").result_with_hash(with: with.to_s, force: force)
|
||||||
|
ENV["RAILS_ENV"] ||= "test"
|
||||||
|
require_relative "../config/environment"
|
||||||
|
require "rails/test_help"
|
||||||
|
|
||||||
|
class ActiveSupport::TestCase
|
||||||
|
<%- if force -%>
|
||||||
|
# Force parallelization, even with single files
|
||||||
|
ActiveSupport.test_parallelization_disabled = false
|
||||||
|
<%- end -%>
|
||||||
|
|
||||||
|
# Run tests in parallel with specified workers
|
||||||
|
parallelize(workers: 2, with: :<%= with %>)
|
||||||
|
|
||||||
|
# Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
|
||||||
|
fixtures :all
|
||||||
|
end
|
||||||
|
ERB
|
||||||
|
|
||||||
app_path("test/test_helper.rb") do |file_name|
|
app_path("test/test_helper.rb") do |file_name|
|
||||||
file = File.read(file_name)
|
File.write(file_name, file_content)
|
||||||
file.sub!(/parallelize\(([^)]*)\)/, "parallelize(workers: 2, with: :#{with})")
|
|
||||||
File.write(file_name, file)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue