Mark unhandled errors in deferreds differently to regular errors.

This commit is contained in:
Jonathan Lange
2010-10-18 13:41:41 +01:00
parent 6d4f32281f
commit 525f5f07b9
4 changed files with 25 additions and 15 deletions

View File

@@ -167,10 +167,10 @@ class AsynchronousDeferredRunTest(RunTest):
successful = False successful = False
# XXX: Maybe we could log creator & invoker here as well if # XXX: Maybe we could log creator & invoker here as well if
# present. # present.
# XXX: Is there anything flagging these as unhandled errors?
for debug_info in unhandled: for debug_info in unhandled:
f = debug_info.failResult f = debug_info.failResult
self._got_user_exception((f.type, f.value, f.tb)) self._got_user_exception(
(f.type, f.value, f.tb), 'unhandled-error-in-deferred')
junk = spinner.clear_junk() junk = spinner.clear_junk()
if junk: if junk:
successful = False successful = False

View File

@@ -146,11 +146,16 @@ class RunTest(object):
except: except:
return self._got_user_exception(sys.exc_info()) return self._got_user_exception(sys.exc_info())
def _got_user_exception(self, exc_info): def _got_user_exception(self, exc_info, tb_label='traceback'):
"""Called when user code raises an exception.""" """Called when user code raises an exception.
:param exc_info: A sys.exc_info() tuple for the user error.
:param tb_label: An optional string label for the error. If
not specified, will default to 'traceback'.
"""
try: try:
e = exc_info[1] e = exc_info[1]
self.case.onException(exc_info) self.case.onException(exc_info, tb_label=tb_label)
finally: finally:
del exc_info del exc_info
for exc_class, handler in self.handlers: for exc_class, handler in self.handlers:

View File

@@ -120,7 +120,9 @@ class TestCase(unittest.TestCase):
unittest.TestCase.__init__(self, *args, **kwargs) unittest.TestCase.__init__(self, *args, **kwargs)
self._cleanups = [] self._cleanups = []
self._unique_id_gen = itertools.count(1) self._unique_id_gen = itertools.count(1)
self._traceback_id_gen = itertools.count(0) # Generators to ensure unique traceback ids. Maps traceback label to
# iterators.
self._traceback_id_gens = {}
self.__setup_called = False self.__setup_called = False
self.__teardown_called = False self.__teardown_called = False
# __details is lazy-initialized so that a constructed-but-not-run # __details is lazy-initialized so that a constructed-but-not-run
@@ -429,14 +431,14 @@ class TestCase(unittest.TestCase):
prefix = self.id() prefix = self.id()
return '%s-%d' % (prefix, self.getUniqueInteger()) return '%s-%d' % (prefix, self.getUniqueInteger())
def onException(self, exc_info): def onException(self, exc_info, tb_label='traceback'):
"""Called when an exception propogates from test code. """Called when an exception propogates from test code.
:seealso addOnException: :seealso addOnException:
""" """
if exc_info[0] not in [ if exc_info[0] not in [
TestSkipped, _UnexpectedSuccess, _ExpectedFailure]: TestSkipped, _UnexpectedSuccess, _ExpectedFailure]:
self._report_traceback(exc_info) self._report_traceback(exc_info, tb_label=tb_label)
for handler in self.__exception_handlers: for handler in self.__exception_handlers:
handler(exc_info) handler(exc_info)
@@ -461,12 +463,12 @@ class TestCase(unittest.TestCase):
self._add_reason(reason) self._add_reason(reason)
result.addSkip(self, details=self.getDetails()) result.addSkip(self, details=self.getDetails())
def _report_traceback(self, exc_info): def _report_traceback(self, exc_info, tb_label='traceback'):
tb_id = advance_iterator(self._traceback_id_gen) id_gen = self._traceback_id_gens.setdefault(
tb_label, itertools.count(0))
tb_id = advance_iterator(id_gen)
if tb_id: if tb_id:
tb_label = 'traceback-%d' % tb_id tb_label = '%s-%d' % (tb_label, tb_id)
else:
tb_label = 'traceback'
self.addDetail(tb_label, content.TracebackContent(exc_info, self)) self.addDetail(tb_label, content.TracebackContent(exc_info, self))
@staticmethod @staticmethod

View File

@@ -345,7 +345,10 @@ class TestAsynchronousDeferredRunTest(TestCase):
('addError', test, None), ('addError', test, None),
('stopTest', test)])) ('stopTest', test)]))
self.assertThat( self.assertThat(
list(error.keys()), Equals(['traceback', 'traceback-1'])) list(error.keys()), Equals([
'unhandled-error-in-deferred',
'unhandled-error-in-deferred-1',
]))
def test_keyboard_interrupt_stops_test_run(self): def test_keyboard_interrupt_stops_test_run(self):
# If we get a SIGINT during a test run, the test stops and no more # If we get a SIGINT during a test run, the test stops and no more
@@ -438,7 +441,7 @@ class TestAsynchronousDeferredRunTest(TestCase):
'traceback', 'traceback',
'traceback-1', 'traceback-1',
'traceback-2', 'traceback-2',
'traceback-3', 'unhandled-error-in-deferred',
])) ]))