From 47bd3ed9ce1bfe9116925b95f4c2b342e864af5a Mon Sep 17 00:00:00 2001 From: ntalbott Date: Thu, 2 Oct 2003 23:03:13 +0000 Subject: * lib/test/unit/assertions.rb: added a default message for #assert, #assert_block, and #flunk. * test/testunit/test_assertions.rb: ditto. * lib/test/unit/failure.rb: failures now show a better trace of where they occurred. * test/testunit/test_failure.rb: ditto (added). * lib/test/unit/testcase.rb: ditto. * test/testunit/test_testcase.rb: ditto. * lib/test/unit/util/backtracefilter.rb: added. * test/testunit/util/test_backtracefilter.rb: added. * lib/test/unit/error.rb: changed to use BacktraceFilter and improved output. * test/testunit/test_error.rb: ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@4657 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 25 ++++++++++++++++++ lib/test/unit/assertions.rb | 6 ++--- lib/test/unit/error.rb | 34 ++++++++---------------- lib/test/unit/failure.rb | 14 +++++++--- lib/test/unit/testcase.rb | 15 +++-------- lib/test/unit/util/backtracefilter.rb | 39 +++++++++++++++++++++++++++ test/testunit/test_assertions.rb | 8 +++--- test/testunit/test_error.rb | 32 ++++++++++------------- test/testunit/test_failure.rb | 33 +++++++++++++++++++++++ test/testunit/test_testcase.rb | 42 +++++++++++++++++++++++++++--- test/testunit/util/test_backtracefilter.rb | 38 +++++++++++++++++++++++++++ 11 files changed, 219 insertions(+), 67 deletions(-) create mode 100644 lib/test/unit/util/backtracefilter.rb create mode 100644 test/testunit/test_failure.rb create mode 100644 test/testunit/util/test_backtracefilter.rb diff --git a/ChangeLog b/ChangeLog index 752aee6c5c..b268f09135 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,28 @@ +Fri Oct 3 08:01:00 2003 Nathaniel Talbott + + * lib/test/unit/assertions.rb: added a default message for #assert, + #assert_block, and #flunk. + + * test/testunit/test_assertions.rb: ditto. + + * lib/test/unit/failure.rb: failures now show a better trace of where + they occurred. + + * test/testunit/test_failure.rb: ditto (added). + + * lib/test/unit/testcase.rb: ditto. + + * test/testunit/test_testcase.rb: ditto. + + * lib/test/unit/util/backtracefilter.rb: added. + + * test/testunit/util/test_backtracefilter.rb: added. + + * lib/test/unit/error.rb: changed to use BacktraceFilter and improved + output. + + * test/testunit/test_error.rb: ditto. + Thu Oct 2 20:33:49 2003 Nobuyoshi Nakada * ext/iconv/iconv.c (iconv_failure_initialize): conform with diff --git a/lib/test/unit/assertions.rb b/lib/test/unit/assertions.rb index 2833eba10d..095af4b3c9 100644 --- a/lib/test/unit/assertions.rb +++ b/lib/test/unit/assertions.rb @@ -25,7 +25,7 @@ module Test # :nodoc: # The assertion upon which all other assertions are # based. Passes if the block yields true. public - def assert_block(message="") # :yields: + def assert_block(message="assert_block failed") # :yields: _wrap_assertion do if (! yield) raise AssertionFailedError.new(message.to_s) @@ -35,7 +35,7 @@ module Test # :nodoc: # Passes if boolean is true. public - def assert(boolean, message="") + def assert(boolean, message="assert failed") _wrap_assertion do assert_block("assert should not be called with a block.") { !block_given? } assert_block(message) { boolean } @@ -199,7 +199,7 @@ module Test # :nodoc: # Always fails. public - def flunk(message="") + def flunk(message="Assertion flunked") assert(false, message) end diff --git a/lib/test/unit/error.rb b/lib/test/unit/error.rb index 46c6663d86..90ac04cf3b 100644 --- a/lib/test/unit/error.rb +++ b/lib/test/unit/error.rb @@ -4,6 +4,8 @@ # Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved. # License:: Ruby license. +require 'test/unit/util/backtracefilter' + module Test module Unit @@ -11,14 +13,16 @@ module Test # Test::Unit::TestCase when it rescues an exception thrown # during the processing of a test. class Error - attr_reader(:location, :exception) + include Util::BacktraceFilter + + attr_reader(:test_name, :exception) SINGLE_CHARACTER = 'E' - # Creates a new Error with the given location and + # Creates a new Error with the given test_name and # exception. - def initialize(location, exception) - @location = location + def initialize(test_name, exception) + @test_name = test_name @exception = exception end @@ -34,35 +38,19 @@ module Test # Returns a brief version of the error description. def short_display - "#{@location}:\n#{message}" + "#@test_name: #{message.split("\n")[0]}" end # Returns a verbose version of the error description. def long_display - backtrace = self.class.filter(@exception.backtrace).join("\n ") - "Error!!!\n#{short_display}\n #{backtrace}" + backtrace = filter_backtrace(@exception.backtrace).join("\n ") + "Error:\n#@test_name:\n#{message}\n #{backtrace}" end # Overridden to return long_display. def to_s long_display end - - SEPARATOR_PATTERN = '[\\\/:]' - def self.filter(backtrace) # :nodoc: - @test_unit_patterns ||= $:.collect { - | path | - /^#{Regexp.escape(path)}#{SEPARATOR_PATTERN}test#{SEPARATOR_PATTERN}unit#{SEPARATOR_PATTERN}/ - }.push(/#{SEPARATOR_PATTERN}test#{SEPARATOR_PATTERN}unit\.rb/) - - return backtrace.delete_if { - | line | - @test_unit_patterns.detect { - | pattern | - line =~ pattern - } - } - end end end end diff --git a/lib/test/unit/failure.rb b/lib/test/unit/failure.rb index 6817d8f3bf..42cc9d4b8c 100644 --- a/lib/test/unit/failure.rb +++ b/lib/test/unit/failure.rb @@ -10,13 +10,14 @@ module Test # Encapsulates a test failure. Created by Test::Unit::TestCase # when an assertion fails. class Failure - attr_reader(:location, :message) + attr_reader :test_name, :location, :message SINGLE_CHARACTER = 'F' # Creates a new Failure with the given location and # message. - def initialize(location, message) + def initialize(test_name, location, message) + @test_name = test_name @location = location @message = message end @@ -28,12 +29,17 @@ module Test # Returns a brief version of the error description. def short_display - "#{@location}:\n#{@message}" + "#@test_name: #{@message.split("\n")[0]}" end # Returns a verbose version of the error description. def long_display - "Failure!!!\n#{short_display}" + location_display = if(location.size == 1) + location[0].sub(/\A(.+:\d+).*/, ' [\\1]') + else + "\n [#{location.join("\n ")}]" + end + "Failure:\n#@test_name#{location_display}:\n#@message" end # Overridden to return long_display. diff --git a/lib/test/unit/testcase.rb b/lib/test/unit/testcase.rb index c831b764a5..f258c23ca1 100644 --- a/lib/test/unit/testcase.rb +++ b/lib/test/unit/testcase.rb @@ -9,6 +9,7 @@ require 'test/unit/failure' require 'test/unit/error' require 'test/unit/testsuite' require 'test/unit/assertionfailederror' +require 'test/unit/util/backtracefilter' module Test module Unit @@ -20,6 +21,7 @@ module Test # collecting its results into a Test::Unit::TestResult object. class TestCase include Assertions + include Util::BacktraceFilter attr_reader :method_name @@ -116,18 +118,7 @@ module Test def add_failure(message, all_locations=caller()) # :nodoc: @test_passed = false - assertions_pattern = /[^A-Za-z_]assertions\.rb:/ - if (all_locations.detect { |entry| entry =~ assertions_pattern }) - all_locations.shift - until (all_locations[0] =~ assertions_pattern || all_locations.empty?) - all_locations.shift - end - location = all_locations.detect { |entry| entry !~ assertions_pattern } - else - location = all_locations[0] - end - location = location[/^.+:\d+/] - @_result.add_failure(Failure.new("#{name} [#{location}]", message)) + @_result.add_failure(Failure.new(name, filter_backtrace(all_locations), message)) end private :add_failure diff --git a/lib/test/unit/util/backtracefilter.rb b/lib/test/unit/util/backtracefilter.rb new file mode 100644 index 0000000000..3a423aa6a1 --- /dev/null +++ b/lib/test/unit/util/backtracefilter.rb @@ -0,0 +1,39 @@ +module Test + module Unit + module Util + module BacktraceFilter + TESTUNIT_FILE_SEPARATORS = %r{[\\/:]} + TESTUNIT_PREFIX = __FILE__.split(TESTUNIT_FILE_SEPARATORS)[0..-3] + TESTUNIT_RB_FILE = /\.rb\Z/ + + def filter_backtrace(backtrace, prefix=nil) + split_p = if(prefix) + prefix.split(TESTUNIT_FILE_SEPARATORS) + else + TESTUNIT_PREFIX + end + match = proc do |e| + split_e = e.split(TESTUNIT_FILE_SEPARATORS)[0, split_p.size] + next false unless(split_e[0..-2] == split_p[0..-2]) + split_e[-1].sub(TESTUNIT_RB_FILE, '') == split_p[-1] + end + return backtrace unless(backtrace.detect(&match)) + found_prefix = false + new_backtrace = backtrace.reverse.reject do |e| + if(match[e]) + found_prefix = true + true + elsif(found_prefix) + false + else + true + end + end.reverse + new_backtrace = (new_backtrace.empty? ? backtrace : new_backtrace) + new_backtrace = new_backtrace.reject(&match) + new_backtrace.empty? ? backtrace : new_backtrace + end + end + end + end +end diff --git a/test/testunit/test_assertions.rb b/test/testunit/test_assertions.rb index ec4b2c0c13..b09986b16f 100644 --- a/test/testunit/test_assertions.rb +++ b/test/testunit/test_assertions.rb @@ -2,7 +2,7 @@ # Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved. # License:: Ruby license. -require 'test/unit/testcase' +require 'test/unit' module Test module Unit @@ -66,7 +66,7 @@ module Test check_nothing_fails { assert_block("successful assert_block") {true} } - check_fails { + check_fails("assert_block failed") { assert_block {false} } check_fails("failed assert_block") { @@ -81,7 +81,7 @@ module Test check_nothing_fails { assert(true, "successful assert") } - check_fails { + check_fails("assert failed") { assert(false) } check_fails("failed assert") { @@ -291,7 +291,7 @@ module Test end def test_flunk - check_fails { + check_fails("Assertion flunked") { flunk } check_fails("flunk message") { diff --git a/test/testunit/test_error.rb b/test/testunit/test_error.rb index c95bef38c4..56b275b362 100644 --- a/test/testunit/test_error.rb +++ b/test/testunit/test_error.rb @@ -2,28 +2,24 @@ # Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved. # License:: Ruby license. -require 'test/unit/error' +require 'test/unit' module Test module Unit class TC_Error < TestCase - def setup - @old_load_path = $:.dup - $:.replace(['C:\some\old\path']) - end - - def test_backtrace_filtering - backtrace = [%q{tc_thing.rb:4:in '/'}] - - backtrace.concat([%q{tc_thing.rb:4:in 'test_stuff'}, - %q{C:\some\old\path/test/unit/testcase.rb:44:in 'send'}, - %q{C:\some\old\path\test\unit\testcase.rb:44:in 'run'}, - %q{tc_thing.rb:3}]) - assert_equal([backtrace[0..1], backtrace[-1]].flatten, Error.filter(backtrace), "Should filter out all TestUnit-specific lines") - end - - def teardown - $:.replace(@old_load_path) + TF_Exception = Struct.new('TF_Exception', :message, :backtrace) + def test_display + ex = TF_Exception.new("message1\nmessage2", ['line1', 'line2']) + e = Error.new("name", ex) + assert_equal("name: #{TF_Exception.name}: message1", e.short_display) + assert_equal(<)", fault.location =~ /test_failure\(TC_FailureError\) \[.*#{File.basename(__FILE__)}:\d+\]/) + check("The Failure should have the correct test_name (was <#{fault.test_name}>)", fault.test_name == "test_failure(TC_FailureError)") + r = /\A.*#{Regexp.escape(File.basename(__FILE__))}:\d+:in `test_failure'\Z/ + + location = fault.location + check("The location should be an array", location.kind_of?(Array)) + check("The location should have two lines (was: <#{location.inspect}>)", location.size == 2) + check("The Failure should have the correct location (was <#{location[0].inspect}>, expected <#{r.inspect}>)", r =~ location[0]) called = true } progress = [] @@ -64,6 +76,30 @@ module Test check("The failure should have set passed?", !test_case.return_passed?) check("The progress block should have been updated correctly", [[TestCase::STARTED, test_case.name], [TestCase::FINISHED, test_case.name]] == progress) end + + def test_add_failure_nested + test_case = @tc_failure_error.new(:test_nested_failure) + check("passed? should start out true", test_case.return_passed?) + + result = TestResult.new + called = false + result.add_listener(TestResult::FAULT) { + | fault | + check("Should have a Failure", fault.instance_of?(Failure)) + check("The Failure should have the correct message", "nested" == fault.message) + check("The Failure should have the correct test_name (was <#{fault.test_name}>)", fault.test_name == "test_nested_failure(TC_FailureError)") + r = + + location = fault.location + check("The location should be an array", location.kind_of?(Array)) + check("The location should have the correct number of lines (was: <#{location.inspect}>)", location.size == 3) + check("The Failure should have the correct location (was <#{location[0].inspect}>)", /\A.*#{Regexp.escape(File.basename(__FILE__))}:\d+:in `nested'\Z/ =~ location[0]) + check("The Failure should have the correct location (was <#{location[1].inspect}>)", /\A.*#{Regexp.escape(File.basename(__FILE__))}:\d+:in `test_nested_failure'\Z/ =~ location[1]) + called = true + } + test_case.run(result){} + check("The failure should have triggered the listener", called) + end def test_add_error test_case = @tc_failure_error.new(:test_error) @@ -74,7 +110,7 @@ module Test | fault | check("Should have a TestError", fault.instance_of?(Error)) check("The Error should have the correct message", "ZeroDivisionError: divided by 0" == fault.message) - check("The Error should have the correct location", "test_error(TC_FailureError)" == fault.location) + check("The Error should have the correct test_name", "test_error(TC_FailureError)" == fault.test_name) check("The Error should have the correct exception", fault.exception.instance_of?(ZeroDivisionError)) called = true } diff --git a/test/testunit/util/test_backtracefilter.rb b/test/testunit/util/test_backtracefilter.rb new file mode 100644 index 0000000000..eeabb91d22 --- /dev/null +++ b/test/testunit/util/test_backtracefilter.rb @@ -0,0 +1,38 @@ +require 'test/unit' + +require 'test/unit/util/backtracefilter' + +module Test::Unit::Util + class TestBacktraceFilter < Test::Unit::TestCase + include BacktraceFilter + + def test_filter_backtrace + backtrace = [%q{C:\some\old\path/test/unit/assertions.rb:44:in 'assert'}, + %q{tc_thing.rb:4:in 'a'}, + %q{tc_thing.rb:4:in 'test_stuff'}, + %q{C:\some\old\path/test/unit/testcase.rb:44:in 'send'}, + %q{C:\some\old\path\test\unit\testcase.rb:44:in 'run'}, + %q{C:\some\old\path\test\unit.rb:44:in 'run'}, + %q{tc_thing.rb:3}] + assert_equal(backtrace[1..2], filter_backtrace(backtrace, %q{C:\some\old\path\test\unit}), "Should filter out all TestUnit-specific lines") + +backtrace = [%q{tc_thing.rb:4:in 'a'}, + %q{tc_thing.rb:4:in 'test_stuff'}, + %q{tc_thing.rb:3}] + assert_equal(backtrace, filter_backtrace(backtrace, %q{C:\some\old\path\test\unit}), "Shouldn't filter too much") + + backtrace = [%q{C:\some\old\path/test/unit/assertions.rb:44:in 'assert'}, + %q{tc_thing.rb:4:in 'a'}, + %q{tc_thing.rb:4:in 'test_stuff'}, + %q{tc_thing.rb:3}] + assert_equal(backtrace[1..3], filter_backtrace(backtrace, %q{C:\some\old\path\test\unit}), "Should filter out all TestUnit-specific lines") + + backtrace = [%q{C:\some\old\path/test/unit/assertions.rb:44:in 'assert'}, + %q{C:\some\old\path/test/unit/testcase.rb:44:in 'send'}, + %q{C:\some\old\path\test\unit\testcase.rb:44:in 'run'}, + %q{C:\some\old\path\test\unit.rb:44:in 'run'}] + assert_equal(backtrace, filter_backtrace(backtrace, %q{C:\some\old\path\test\unit}), "Should filter out all TestUnit-specific lines") + + end + end +end -- cgit v1.2.3