class Minitest::TestTask
def self.create name = :test, &block
def self.create name = :test, &block task = new name task.instance_eval(&block) if block task.process_env task.define task end
def define # :nodoc:
def define # :nodoc: desc "Run the test suite. Use N, X, A, and TESTOPTS to add flags/args." task name do ruby make_test_cmd, verbose:verbose end desc "Print out the test command. Good for profiling and other tools." task "#{name}:cmd" do puts "ruby #{make_test_cmd}" end desc "Show which test files fail when run in isolation." task "#{name}:isolated" do tests = Dir[*self.test_globs].uniq # 3 seems to be the magic number... (tho not by that much) bad, good, n = {}, [], (ENV.delete("K") || 3).to_i file = ENV.delete("F") times = {} tt0 = Time.now n.threads_do tests.sort do |path| t0 = Time.now output = `#{Gem.ruby} #{make_test_cmd path} 2>&1` t1 = Time.now - t0 times[path] = t1 if $?.success? $stderr.print "." good << path else $stderr.print "x" bad[path] = output end end puts "done" puts "Ran in %.2f seconds" % [ Time.now - tt0 ] if file then require "json" File.open file, "w" do |io| io.puts JSON.pretty_generate times end end unless good.empty? puts puts "# Good tests:" puts good.sort.each do |path| puts "%.2fs: %s" % [times[path], path] end end unless bad.empty? puts puts "# Bad tests:" puts bad.keys.sort.each do |path| puts "%.2fs: %s" % [times[path], path] end puts puts "# Bad Test Output:" puts bad.sort.each do |path, output| puts puts "# #{path}:" puts output end exit 1 end end task "#{name}:deps" => "#{name}:isolated" # now just an alias desc "Show bottom 25 tests wrt time." task "#{name}:slow" do sh ["rake #{name} A=-v", "egrep '#test_.* s = .'", "sort -n -k2 -t=", "tail -25"].join " | " end end
def initialize name = :test # :nodoc:
def initialize name = :test # :nodoc: self.extra_args = [] self.framework = %(require "minitest/autorun") self.libs = %w[lib test .] self.name = name self.test_globs = ["test/**/test_*.rb", "test/**/*_test.rb"] self.test_prelude = nil self.verbose = Rake.application.options.trace self.warning = true end
def make_test_cmd globs = test_globs
def make_test_cmd globs = test_globs tests = [] tests.concat Dir[*globs].sort.shuffle # TODO: SEED -> srand first? tests.map! { |f| %(require "#{f}") } runner = [] runner << test_prelude if test_prelude runner << framework runner.concat tests runner = runner.join "; " args = [] args << "-I#{libs.join(File::PATH_SEPARATOR)}" unless libs.empty? args << "-w" if warning args << '-e' args << "'#{runner}'" args << '--' args << extra_args.map(&:shellescape) args.join " " end
def process_env
def process_env warn "TESTOPTS is deprecated in Minitest::TestTask. Use A instead" if ENV["TESTOPTS"] warn "FILTER is deprecated in Minitest::TestTask. Use A instead" if ENV["FILTER"] warn "N is deprecated in Minitest::TestTask. Use MT_CPU instead" if ENV["N"] && ENV["N"].to_i > 0 lib_extras = (ENV["MT_LIB_EXTRAS"] || "").split File::PATH_SEPARATOR self.libs[0,0] = lib_extras extra_args << "-n" << ENV["N"] if ENV["N"] extra_args << "-e" << ENV["X"] if ENV["X"] extra_args.concat Shellwords.split(ENV["TESTOPTS"]) if ENV["TESTOPTS"] extra_args.concat Shellwords.split(ENV["FILTER"]) if ENV["FILTER"] extra_args.concat Shellwords.split(ENV["A"]) if ENV["A"] ENV.delete "N" if ENV["N"] # TODO? RUBY_DEBUG = ENV["RUBY_DEBUG"] # TODO? ENV["RUBY_FLAGS"] extra_args.compact! end