require "test/unit" require "fileutils" require "tmpdir" require "test-unit-ext/attributes" module Test module Unit class TestCase class << self def priority(name, *tests) singleton_class = (class << self; self; end) priority_check_method = priority_check_method_name(name) unless singleton_class.private_method_defined?(priority_check_method) raise ArgumentError, "unknown priority: #{name}" end attribute(:priority, name, {:keep => true}, *tests) end def need_to_run?(test_name) priority = (attributes(test_name) || {})[:priority] || :normal __send__(priority_check_method_name(priority), test_name) end private def priority_check_method_name(priority_name) "run_priority_#{priority_name}?" end def set_priority(name, priority=@current_priority) @priority_table[normalize_test_name(name)] = priority end def run_priority_must?(test_name) true end def run_priority_important?(test_name) rand > 0.1 end def run_priority_high?(test_name) rand > 0.3 end def run_priority_normal?(test_name) rand > 0.5 end def run_priority_low?(test_name) rand > 0.75 end def run_priority_never?(test_name) false end end def need_to_run? !previous_test_success? or self.class.need_to_run?(@method_name) end alias_method :run_without_priority, :run def run(result, &block) run_without_priority(result, &block) ensure if passed? FileUtils.touch(passed_file) else FileUtils.rm_f(passed_file) end end private def previous_test_success? File.exist?(passed_file) end def result_dir components = [".test-result", self.class.name, @method_name.to_s] parent_directories = [File.dirname($0), File.join(File.dirname(__FILE__), ".."), Dir.pwd] if Process.respond_to?(:uid) parent_directories << File.join(Dir.tmpdir, Process.uid.to_s) end parent_directories.each do |parent_directory| dir = File.expand_path(File.join(parent_directory, *components)) begin FileUtils.mkdir_p(dir) return dir rescue Errno::EACCES end end raise Errno::EACCES, parent_directories.join(", ") end def passed_file File.join(result_dir, "passed") end def escaped_method_name @method_name.to_s.gsub(/[!?]$/) do |matched| case matched when "!" ".destructive" when "?" ".predicate" end end end end class TestSuite @@priority_mode = false class << self def priority_mode=(bool) @@priority_mode = bool end end alias_method :run_without_priority_support, :run def run(*args, &block) priority_mode = @@priority_mode if priority_mode @original_tests = @tests apply_priority end run_without_priority_support(*args, &block) ensure @tests = @original_tests if priority_mode end def apply_priority @tests = @tests.reject {|test| !test.need_to_run?} end def need_to_run? apply_priority !@tests.empty? end end class AutoRunner alias_method :options_without_priority, :options def options opts = options_without_priority opts.on("--[no-]priority", "use priority mode") do |bool| TestSuite.priority_mode = bool end opts end end end end