diff options
Diffstat (limited to 'lib/testtools/testtools/testresult/real.py')
-rw-r--r-- | lib/testtools/testtools/testresult/real.py | 67 |
1 files changed, 49 insertions, 18 deletions
diff --git a/lib/testtools/testtools/testresult/real.py b/lib/testtools/testtools/testresult/real.py index 8c8a3edd6e..95f6e8f04c 100644 --- a/lib/testtools/testtools/testresult/real.py +++ b/lib/testtools/testtools/testresult/real.py @@ -13,6 +13,8 @@ __all__ = [ import datetime import unittest +from testtools.compat import _format_exc_info, str_is_unicode, _u + class TestResult(unittest.TestResult): """Subclass of unittest.TestResult extending the protocol for flexability. @@ -105,10 +107,27 @@ class TestResult(unittest.TestResult): """Called when a test was expected to fail, but succeed.""" self.unexpectedSuccesses.append(test) + if str_is_unicode: + # Python 3 and IronPython strings are unicode, use parent class method + _exc_info_to_unicode = unittest.TestResult._exc_info_to_string + else: + # For Python 2, need to decode components of traceback according to + # their source, so can't use traceback.format_exception + # Here follows a little deep magic to copy the existing method and + # replace the formatter with one that returns unicode instead + from types import FunctionType as __F, ModuleType as __M + __f = unittest.TestResult._exc_info_to_string.im_func + __g = dict(__f.func_globals) + __m = __M("__fake_traceback") + __m.format_exception = _format_exc_info + __g["traceback"] = __m + _exc_info_to_unicode = __F(__f.func_code, __g, "_exc_info_to_unicode") + del __F, __M, __f, __g, __m + def _err_details_to_string(self, test, err=None, details=None): """Convert an error in exc_info form or a contents dict to a string.""" if err is not None: - return self._exc_info_to_string(err, test) + return self._exc_info_to_unicode(err, test) return _details_to_str(details) def _now(self): @@ -165,41 +184,43 @@ class MultiTestResult(TestResult): self._results = map(ExtendedToOriginalDecorator, results) def _dispatch(self, message, *args, **kwargs): - for result in self._results: + return tuple( getattr(result, message)(*args, **kwargs) + for result in self._results) def startTest(self, test): - self._dispatch('startTest', test) + return self._dispatch('startTest', test) def stopTest(self, test): - self._dispatch('stopTest', test) + return self._dispatch('stopTest', test) def addError(self, test, error=None, details=None): - self._dispatch('addError', test, error, details=details) + return self._dispatch('addError', test, error, details=details) def addExpectedFailure(self, test, err=None, details=None): - self._dispatch('addExpectedFailure', test, err, details=details) + return self._dispatch( + 'addExpectedFailure', test, err, details=details) def addFailure(self, test, err=None, details=None): - self._dispatch('addFailure', test, err, details=details) + return self._dispatch('addFailure', test, err, details=details) def addSkip(self, test, reason=None, details=None): - self._dispatch('addSkip', test, reason, details=details) + return self._dispatch('addSkip', test, reason, details=details) def addSuccess(self, test, details=None): - self._dispatch('addSuccess', test, details=details) + return self._dispatch('addSuccess', test, details=details) def addUnexpectedSuccess(self, test, details=None): - self._dispatch('addUnexpectedSuccess', test, details=details) + return self._dispatch('addUnexpectedSuccess', test, details=details) def startTestRun(self): - self._dispatch('startTestRun') + return self._dispatch('startTestRun') def stopTestRun(self): - self._dispatch('stopTestRun') + return self._dispatch('stopTestRun') def done(self): - self._dispatch('done') + return self._dispatch('done') class TextTestResult(TestResult): @@ -508,13 +529,23 @@ class ExtendedToOriginalDecorator(object): class _StringException(Exception): """An exception made from an arbitrary string.""" + if not str_is_unicode: + def __init__(self, string): + if type(string) is not unicode: + raise TypeError("_StringException expects unicode, got %r" % + (string,)) + Exception.__init__(self, string) + + def __str__(self): + return self.args[0].encode("utf-8") + + def __unicode__(self): + return self.args[0] + # For 3.0 and above the default __str__ is fine, so we don't define one. + def __hash__(self): return id(self) - def __str__(self): - """Stringify better than 2.x's default behaviour of ascii encoding.""" - return self.args[0] - def __eq__(self, other): try: return self.args == other.args @@ -537,4 +568,4 @@ def _details_to_str(details): if not chars[-1].endswith('\n'): chars.append('\n') chars.append('------------\n') - return ''.join(chars) + return _u('').join(chars) |