diff options
-rw-r--r-- | CHANGELOG | 1 | ||||
-rw-r--r-- | nose/plugins/capture.py | 2 | ||||
-rw-r--r-- | nose/proxy.py | 23 | ||||
-rw-r--r-- | nosetests.1 | 2 | ||||
-rw-r--r-- | unit_tests/test_result_proxy.py | 26 |
5 files changed, 43 insertions, 11 deletions
@@ -7,6 +7,7 @@ - Fixed problems with SkipTest in Python 3.2 (#389) - Fixes Xunit plugin to handle non-UTF8 characters (#395) - Makes --plugins more succinct when there are no options (#235) +- Fixes mishandling of custom exceptions during failures (#405) - Fixes capture plugin when exception message contains non-ascii chars (#402) - Fixed bug in doctest plugin under python 3. Thanks to Thomas Kluyver for the patch. (#391) diff --git a/nose/plugins/capture.py b/nose/plugins/capture.py index 1616132..911215d 100644 --- a/nose/plugins/capture.py +++ b/nose/plugins/capture.py @@ -94,7 +94,7 @@ class Capture(Plugin): # 2.5- if not hasattr(ev, 'message'): # 2.4 - msg = ev.args[0] + msg = len(ev.args) and ev.args[0] or '' else: msg = ev.message if not isinstance(msg, unicode): diff --git a/nose/proxy.py b/nose/proxy.py index 0d31d67..8723290 100644 --- a/nose/proxy.py +++ b/nose/proxy.py @@ -85,6 +85,19 @@ class ResultProxy(object): def __repr__(self): return repr(self.result) + def _prepareErr(self, err): + if not isinstance(err[1], Exception): + # Turn value back into an Exception (required in Python 3.x). + # Plugins do all sorts of crazy things with exception values. + try: + # The actual exception class is needed for failure detail + # but maybe other plugins? + value = err[0](err[1]) + except: + value = Exception(err[1]) + err = (err[0], value, err[2]) + return err + def assertMyTest(self, test): # The test I was called with must be my .test or my # .test's .test. or my .test.test's .case @@ -117,12 +130,9 @@ class ResultProxy(object): # test.passed is set in result, to account for error classes formatted = plugins.formatError(self.test, err) if formatted is not None: - if isinstance(formatted[1], basestring): - # Turn it back into an Exception (required in Python 3.x) - formatted = (formatted[0], Exception(formatted[1]), formatted[2]) err = formatted plugins.addError(self.test, err) - self.result.addError(self.test, err) + self.result.addError(self.test, self._prepareErr(err)) if not self.result.wasSuccessful() and self.config.stopOnError: self.shouldStop = True @@ -136,10 +146,8 @@ class ResultProxy(object): formatted = plugins.formatFailure(self.test, err) if formatted is not None: err = formatted - if not isinstance(err[1], Exception): - err = (err[0], err[0](err[1]), err[2]) plugins.addFailure(self.test, err) - self.result.addFailure(self.test, err) + self.result.addFailure(self.test, self._prepareErr(err)) if self.config.stopOnError: self.shouldStop = True @@ -181,4 +189,3 @@ class ResultProxy(object): """Tests that failed""") testsRun = proxied_attribute('result', 'testsRun', """Number of tests run""") - diff --git a/nosetests.1 b/nosetests.1 index d58795b..b26af41 100644 --- a/nosetests.1 +++ b/nosetests.1 @@ -466,5 +466,5 @@ jpellerin+nose@gmail.com .SH COPYRIGHT LGPL -.\" Generated by docutils manpage writer on 2011-03-21 10:52. +.\" Generated by docutils manpage writer on 2011-03-22 09:55. .\" diff --git a/unit_tests/test_result_proxy.py b/unit_tests/test_result_proxy.py index 9ed1e11..3d6e2ac 100644 --- a/unit_tests/test_result_proxy.py +++ b/unit_tests/test_result_proxy.py @@ -159,6 +159,30 @@ class TestResultProxy(unittest.TestCase): case(proxy) assert proxy.shouldStop assert res.shouldStop - + + def test_coercion_of_custom_exception(self): + from nose.case import Test + + class CustomException(Exception): + def __init__(self, message, two, three): + Exception.__init__(self, message) + + class TC(unittest.TestCase): + def runTest(self): + pass + + test = TC() + case = Test(test) + res = unittest.TestResult() + try: + raise CustomException("the error", 2, 3) + except: + etype, val, tb = sys.exc_info() + val = str(val) # simulate plugin shenanigans + proxy = ResultProxy(res, test=case) + # Python 3 coercion should happen here without error + proxy.addError(test, (etype, val, tb)) + proxy.addFailure(test, (etype, val, tb)) + if __name__ == '__main__': unittest.main() |