activesupport/lib/active_support/testing/parallelize_executor.rb
# frozen_string_literal: true
module ActiveSupport
module Testing
class ParallelizeExecutor # :nodoc:
attr_reader :size, :parallelize_with, :threshold
def initialize(size:, with:, threshold: ActiveSupport.test_parallelization_threshold)
@size = size
@parallelize_with = with
@threshold = threshold
@parallelized = false
end
def start
parallelize if should_parallelize?
show_execution_info
parallel_executor.start if parallelized?
end
def <<(work)
parallel_executor << work if parallelized?
end
def shutdown
parallel_executor.shutdown if parallelized?
end
private
def parallel_executor
@parallel_executor ||= build_parallel_executor
end
def build_parallel_executor
case parallelize_with
when :processes
Testing::Parallelization.new(size)
when :threads
ActiveSupport::TestCase.lock_threads = false if defined?(ActiveSupport::TestCase.lock_threads)
Minitest::Parallel::Executor.new(size)
else
raise ArgumentError, "#{parallelize_with} is not a supported parallelization executor."
end
end
def parallelize
@parallelized = true
Minitest::Test.parallelize_me!
end
def parallelized?
@parallelized
end
def should_parallelize?
(ENV["PARALLEL_WORKERS"] || tests_count > threshold) && many_workers?
end
def many_workers?
size > 1
end
def tests_count
@tests_count ||= Minitest::Runnable.runnables.sum { |runnable| runnable.runnable_methods.size }
end
def show_execution_info
puts execution_info
end
def execution_info
if parallelized?
"Running #{tests_count} tests in parallel using #{parallel_executor.size} #{parallelize_with}"
elsif many_workers?
"Running #{tests_count} tests in a single process (parallelization threshold is #{threshold})"
end
end
end
end
end