# frozen_string_literal: true require "rake/testtask" task default: :test task :package desc "Run all unit tests" task test: "test:isolated" namespace :test do task :isolated do estimated_duration = { "test/application/test_runner_test.rb" => 201, "test/application/assets_test.rb" => 131, "test/application/rake/migrations_test.rb" => 65, "test/generators/scaffold_generator_test.rb" => 57, "test/generators/plugin_test_runner_test.rb" => 57, "test/application/test_test.rb" => 52, "test/application/configuration_test.rb" => 49, "test/generators/app_generator_test.rb" => 43, "test/application/rake/dbs_test.rb" => 43, "test/application/rake_test.rb" => 33, "test/generators/plugin_generator_test.rb" => 30, "test/railties/engine_test.rb" => 27, "test/generators/scaffold_controller_generator_test.rb" => 23, "test/railties/generators_test.rb" => 19, "test/application/console_test.rb" => 16, "test/engine/commands_test.rb" => 15, "test/application/routing_test.rb" => 15, "test/application/mailer_previews_test.rb" => 15, "test/application/rake/multi_dbs_test.rb" => 13, "test/application/asset_debugging_test.rb" => 12, "test/application/bin_setup_test.rb" => 11, "test/engine/test_test.rb" => 10, "test/application/runner_test.rb" => 10, } estimated_duration.default = 1 dash_i = [ "test", "lib", "../activesupport/lib", "../actionpack/lib", "../actionview/lib", "../activemodel/lib" ].map { |dir| File.expand_path(dir, __dir__) } dash_i.reverse_each do |x| $:.unshift(x) unless $:.include?(x) end $-w = true require "bundler/setup" unless defined?(Bundler) require "active_support" # Only generate the template app once. require_relative "test/isolation/abstract_unit" failing_files = [] dirs = (ENV["TEST_DIR"] || ENV["TEST_DIRS"] || "**").split(",") test_options = ENV["TESTOPTS"].to_s.split(/[\s]+/) test_patterns = dirs.map { |dir| "test/#{dir}/*_test.rb" } test_files = Dir[*test_patterns].select do |file| !file.start_with?("test/fixtures/") && !file.start_with?("test/isolation/assets/") end if ENV["BUILDKITE_PARALLEL_JOB_COUNT"] n = ENV["BUILDKITE_PARALLEL_JOB"].to_i m = ENV["BUILDKITE_PARALLEL_JOB_COUNT"].to_i buckets = Array.new(m) { [] } allocations = Array.new(m) { 0 } test_files.sort_by { |file| [-estimated_duration[file], file] }.each do |file| idx = allocations.index(allocations.min) buckets[idx] << file allocations[idx] += estimated_duration[file] end puts "Running #{buckets[n].size} of #{test_files.size} test files, estimated duration #{allocations[n]}s" test_files = buckets[n] end test_files.each do |file| puts "--- #{file}" fake_command = Shellwords.join([ FileUtils::RUBY, "-w", *dash_i.map { |dir| "-I#{Pathname.new(dir).relative_path_from(Pathname.pwd)}" }, file, ]) puts fake_command if Process.respond_to?(:fork) # We could run these in parallel, but pretty much all of the # railties tests already run in parallel, so ¯\_(⊙︿⊙)_/¯ Process.waitpid fork { ARGV.clear.concat test_options Rake.application = nil load file } else Process.wait spawn(fake_command) end unless $?.success? failing_files << file puts "^^^ +++" end end puts "--- All tests completed" unless failing_files.empty? puts "^^^ +++" puts puts "Failed in:" failing_files.each do |file| puts " #{file}" end puts exit 1 end end end Rake::TestTask.new("test:regular") do |t| t.libs << "test" << "#{__dir__}/../activesupport/lib" t.pattern = "test/**/*_test.rb" t.warning = true t.verbose = true t.ruby_opts = ["--dev"] if defined?(JRUBY_VERSION) end