1#-- 2# 3# Author:: Nathaniel Talbott. 4# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved. 5# License:: Ruby license. 6 7module Test 8 module Unit 9 10 # Encapsulates a test failure. Created by Test::Unit::TestCase 11 # when an assertion fails. 12 class Failure 13 attr_reader :test_name, :location, :message 14 attr_reader :method_name, :source_location 15 attr_reader :expected, :actual, :user_message 16 attr_reader :inspected_expected, :inspected_actual 17 18 SINGLE_CHARACTER = 'F' 19 LABEL = "Failure" 20 21 # Creates a new Failure with the given location and 22 # message. 23 def initialize(test_name, location, message, options={}) 24 @test_name = test_name 25 @location = location 26 @message = message 27 @method_name = options[:method_name] 28 @source_location = options[:source_location] 29 @expected = options[:expected] 30 @actual = options[:actual] 31 @inspected_expected = options[:inspected_expected] 32 @inspected_actual = options[:inspected_actual] 33 @user_message = options[:user_message] 34 end 35 36 # Returns a single character representation of a failure. 37 def single_character_display 38 SINGLE_CHARACTER 39 end 40 41 def label 42 LABEL 43 end 44 45 # Returns a brief version of the error description. 46 def short_display 47 "#@test_name: #{@message.split("\n")[0]}" 48 end 49 50 # Returns a verbose version of the error description. 51 def long_display 52 if location.size == 1 53 location_display = location[0].sub(/\A(.+:\d+).*/, ' [\\1]') 54 else 55 location_display = "\n [#{location.join("\n ")}]" 56 end 57 "#{label}:\n#@test_name#{location_display}:\n#@message" 58 end 59 60 # Overridden to return long_display. 61 def to_s 62 long_display 63 end 64 65 def critical? 66 true 67 end 68 69 def diff 70 @diff ||= compute_diff 71 end 72 73 private 74 def compute_diff 75 Assertions::AssertionMessage.delayed_diff(@expected, @actual).inspect 76 end 77 end 78 79 module FailureHandler 80 class << self 81 def included(base) 82 base.exception_handler(:handle_assertion_failed_error) 83 end 84 end 85 86 # Report a failure. 87 # 88 # This is a public API for developers who extend test-unit. 89 # 90 # @param message [String] The description about the failure. 91 # @param backtrace [Array<String>] The backtrace for the failure. 92 # @option options [Object] :expected 93 # The expected value of the assertion. 94 # @option options [Object] :actual 95 # The actual value of the assertion. 96 # @option options [String] :inspected_expected 97 # The inspected expected value of the assertion. 98 # It is used for diff between expected and actual of the failure. 99 # @option options [String] :inspected_actual 100 # The inspected actual value of the assertion. 101 # It is used for diff between expected and actual of the failure. 102 # @option options [String] :user_message 103 # The message of the assertion from user. 104 # @option options [String] :method_name (@method_name) 105 # The method name of the test. 106 # @option options [Array<String, Integer>] :source_location 107 # The location where the test is defined. It is the same 108 # format as Proc#source_location. That is, it's an array of 109 # path and and line number where the test definition is 110 # started. 111 # @return [void] 112 def add_failure(message, backtrace, options={}) 113 default_options = { 114 :method_name => @method_name, 115 :source_location => self[:source_location], 116 } 117 failure = Failure.new(name, filter_backtrace(backtrace), message, 118 default_options.merge(options)) 119 current_result.add_failure(failure) 120 end 121 122 private 123 def handle_assertion_failed_error(exception) 124 return false unless exception.is_a?(AssertionFailedError) 125 problem_occurred 126 add_failure(exception.message, exception.backtrace, 127 :expected => exception.expected, 128 :actual => exception.actual, 129 :inspected_expected => exception.inspected_expected, 130 :inspected_actual => exception.inspected_actual, 131 :user_message => exception.user_message) 132 true 133 end 134 end 135 136 module TestResultFailureSupport 137 attr_reader :failures 138 139 # Records a Test::Unit::Failure. 140 def add_failure(failure) 141 @failures << failure 142 notify_fault(failure) 143 notify_changed 144 end 145 146 # Returns the number of failures this TestResult has 147 # recorded. 148 def failure_count 149 @failures.size 150 end 151 152 def failure_occurred? 153 not @failures.empty? 154 end 155 156 private 157 def initialize_containers 158 super 159 @failures = [] 160 @summary_generators << :failure_summary 161 @problem_checkers << :failure_occurred? 162 end 163 164 def failure_summary 165 "#{failure_count} failures" 166 end 167 end 168 end 169end 170