summaryrefslogtreecommitdiffstats
path: root/Lib/unittest.py
diff options
context:
space:
mode:
authorSteve Purcell <steve@pythonconsulting.com>2003-12-06 13:03:13 (GMT)
committerSteve Purcell <steve@pythonconsulting.com>2003-12-06 13:03:13 (GMT)
commitb8d5f245b7077d869121835ed72656ac14962ef0 (patch)
tree1c9896f4fc19fec6bfc54a2100910b049a4c7231 /Lib/unittest.py
parentff6dd0b7d005dcd207195962ac5210a3e3455348 (diff)
downloadcpython-b8d5f245b7077d869121835ed72656ac14962ef0.zip
cpython-b8d5f245b7077d869121835ed72656ac14962ef0.tar.gz
cpython-b8d5f245b7077d869121835ed72656ac14962ef0.tar.bz2
Variation of Thomas Heller's patch (722638) for improving readability
of test failure output. Irrelevant traceback levels are pruned from formatted traceback strings.
Diffstat (limited to 'Lib/unittest.py')
-rw-r--r--Lib/unittest.py36
1 files changed, 26 insertions, 10 deletions
diff --git a/Lib/unittest.py b/Lib/unittest.py
index 10108d3..0ec059c 100644
--- a/Lib/unittest.py
+++ b/Lib/unittest.py
@@ -46,7 +46,7 @@ SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
__author__ = "Steve Purcell"
__email__ = "stephen_purcell at yahoo dot com"
-__version__ = "#Revision: 1.62 $"[11:-2]
+__version__ = "#Revision: 1.63 $"[11:-2]
import time
import sys
@@ -90,6 +90,8 @@ __metaclass__ = type
def _strclass(cls):
return "%s.%s" % (cls.__module__, cls.__name__)
+__unittest = 1
+
class TestResult:
"""Holder for test result information.
@@ -119,12 +121,12 @@ class TestResult:
"""Called when an error has occurred. 'err' is a tuple of values as
returned by sys.exc_info().
"""
- self.errors.append((test, self._exc_info_to_string(err)))
+ self.errors.append((test, self._exc_info_to_string(err, test)))
def addFailure(self, test, err):
"""Called when an error has occurred. 'err' is a tuple of values as
returned by sys.exc_info()."""
- self.failures.append((test, self._exc_info_to_string(err)))
+ self.failures.append((test, self._exc_info_to_string(err, test)))
def addSuccess(self, test):
"Called when a test has completed successfully"
@@ -138,16 +140,33 @@ class TestResult:
"Indicates that the tests should be aborted"
self.shouldStop = True
- def _exc_info_to_string(self, err):
+ def _exc_info_to_string(self, err, test):
"""Converts a sys.exc_info()-style tuple of values into a string."""
- return ''.join(traceback.format_exception(*err))
+ exctype, value, tb = err
+ # Skip test runner traceback levels
+ while tb and self._is_relevant_tb_level(tb):
+ tb = tb.tb_next
+ if exctype is test.failureException:
+ # Skip assert*() traceback levels
+ length = self._count_relevant_tb_levels(tb)
+ return ''.join(traceback.format_exception(exctype, value, tb, length))
+ return ''.join(traceback.format_exception(exctype, value, tb))
+
+ def _is_relevant_tb_level(self, tb):
+ return tb.tb_frame.f_globals.has_key('__unittest')
+
+ def _count_relevant_tb_levels(self, tb):
+ length = 0
+ while tb and not self._is_relevant_tb_level(tb):
+ length += 1
+ tb = tb.tb_next
+ return length
def __repr__(self):
return "<%s run=%i errors=%i failures=%i>" % \
(_strclass(self.__class__), self.testsRun, len(self.errors),
len(self.failures))
-
class TestCase:
"""A class whose instances are single test cases.
@@ -274,10 +293,7 @@ class TestCase:
exctype, excvalue, tb = sys.exc_info()
if sys.platform[:4] == 'java': ## tracebacks look different in Jython
return (exctype, excvalue, tb)
- newtb = tb.tb_next
- if newtb is None:
- return (exctype, excvalue, tb)
- return (exctype, excvalue, newtb)
+ return (exctype, excvalue, tb)
def fail(self, msg=None):
"""Fail immediately, with the given message."""