# frozen_string_literal: true require "shellwords" 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" => 179, "test/application/assets_test.rb" => 20, "test/application/rake/migrations_test.rb" => 90, "test/generators/scaffold_generator_test.rb" => 78, "test/generators/plugin_test_runner_test.rb" => 73, "test/application/test_test.rb" => 25, "test/application/configuration_test.rb" => 106, "test/generators/app_generator_test.rb" => 150, "test/application/rake/dbs_test.rb" => 82, "test/application/rake_test.rb" => 33, "test/generators/plugin_generator_test.rb" => 37, "test/railties/engine_test.rb" => 39, "test/generators/scaffold_controller_generator_test.rb" => 27, "test/railties/generators_test.rb" => 25, "test/application/console_test.rb" => 20, "test/engine/commands_test.rb" => 17, "test/application/routing_test.rb" => 21, "test/application/mailer_previews_test.rb" => 20, "test/application/rake/multi_dbs_test.rb" => 100, "test/application/asset_debugging_test.rb" => 5, "test/application/bin_setup_test.rb" => 13, "test/engine/test_test.rb" => 16, "test/application/runner_test.rb" => 13, "test/commands/routes_test.rb" => 7, "test/application/initializers/i18n_test.rb" => 8, "test/application/middleware/cache_test.rb" => 7, "test/application/middleware_test.rb" => 10, "test/generators/test_runner_in_engine_test.rb" => 7, "test/application/initializers/frameworks_test.rb" => 18, "test/application/middleware/exceptions_test.rb" => 12, "test/application/content_security_policy_test.rb" => 5, } 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