require "test/unit" module Test module Unit class TestCase class << self alias_method :method_added_without_metadata, :method_added def method_added(name) method_added_without_metadata(name) if defined?(@current_metadata) set_metadata(name, @current_metadata) @current_metadata = {} end end def metadata(name, value, *tests) @current_metadata ||= {} if tests.empty? @current_metadata[name] = value else tests.each do |test| set_metadata(test, {name => value}) end end end def bug(value, *tests) metadata(:bug, value, *tests) end def set_metadata(test_name, metadata) return if metadata.empty? test_name = normalize_test_name(test_name) @metadata ||= {} @metadata[test_name] ||= {} @metadata[test_name] = @metadata[test_name].merge(metadata) end def get_metadata(test_name) test_name = normalize_test_name(test_name) @metadata ||= {} @metadata[test_name] end end alias_method :run_without_metadata, :run def run(result, &block) run_without_metadata(TestResultMetadataSupport.new(result, self), &block) end def metadata self.class.get_metadata(@method_name) || {} end end class TestResultMetadataSupport def initialize(result, test) @result = result @test = test end def add_failure(failure) failure.metadata = @test.metadata method_missing(:add_failure, failure) end def add_error(error) error.metadata = @test.metadata method_missing(:add_error, error) end def method_missing(name, *args, &block) @result.send(name, *args, &block) end end module MetadataFormatter private def format_metadata return '' if metadata.empty? metadata.collect do |key, value| " #{key}: #{value}" end.join("\n") + "\n" end end class Failure include MetadataFormatter attr_accessor :metadata alias_method :long_display_without_metadata, :long_display def long_display long_display_without_metadata.sub(/(^#{Regexp.escape(@test_name)}.*\n)/, "\\1#{format_metadata}") end end class Error include MetadataFormatter attr_accessor :metadata alias_method :long_display_without_metadata, :long_display def long_display long_display_without_metadata.sub(/(^#{Regexp.escape(@test_name)}:\n)/, "\\1#{format_metadata}") end end end end