It is the job of TestResult.addError()
to format exceptions:
Called when the test case test raises an unexpected exception. err is a tuple of the form returned by sys.exc_info()
: (type, value, traceback)
.
The default implementation appends a tuple (test, formatted_err)
to the instance’s errors
attribute, where formatted_err is a formatted traceback derived from err.
If you want to format your tracebacks differently, this is where you'd step in to change them. You have two options:
- Write your own traceback formatter (to replace the current implementation)
- Post-process the
formatted_err
value that the base implementation adds.
The latter might be simpler; just delete any further indented lines following a line that starts with ' File'
:
import re
import unittest
from functools import partial
# traceback `File` lines are followed by an optional source line, and if
# locals are included, by <name> = <value> lines:
_tb_file_line = re.compile(
r'( File "[^"]*", line \d+, in [^\n]+\n)'
r' [^ ].*\n'
r'(?: \w+ = .*\n)*'
)
_clear_source_and_locals = partial(_tb_file_line.sub, r'\1')
class NoSourceTracebackResult(unittest.TextTestResult):
def addError(self, test, err):
super().addError(test, err)
# remove error, format, then put it back again
t, formatted_err = self.errors.pop()
formatted_err = _clear_source_and_locals(formatted_err)
self.errors.append((test, formatted_err))
class NoSourceTracebackRunner(unittest.TextTestRunner):
resultclass = NoSourceTracebackResult
then use that as your test runner; if you run with unittest.main()
in a __main__
guard, then use it like this:
if __name__ == '__main__':
unittest.main(testRunner=NoSourceTracebackRunner)(