Getting Python’s unittest results in a tearDown() method

As of March 2022 this answer is updated to support Python versions between 3.4 and 3.11 (including the newest development Python version). Classification of errors / failures is the same that is used in the output unittest. It works without any modification of code before tearDown(). It correctly recognizes decorators skipIf() and expectedFailure. It is compatible also with pytest.

Code:

import unittest

class MyTest(unittest.TestCase):
    def tearDown(self):
        if hasattr(self._outcome, 'errors'):
            # Python 3.4 - 3.10  (These two methods have no side effects)
            result = self.defaultTestResult()
            self._feedErrorsToResult(result, self._outcome.errors)
        else:
            # Python 3.11+
            result = self._outcome.result
        ok = all(test != self for test, text in result.errors + result.failures)

        # Demo output:  (print short info immediately - not important)
        if ok:
            print('\nOK: %s' % (self.id(),))
        for typ, errors in (('ERROR', result.errors), ('FAIL', result.failures)):
            for test, text in errors:
                if test is self:
                    #  the full traceback is in the variable `text`
                    msg = [x for x in text.split('\n')[1:]
                           if not x.startswith(' ')][0]
                    print("\n\n%s: %s\n     %s" % (typ, self.id(), msg))

If you don’t need the exception info then the second half can be removed. If you want also the tracebacks then use the whole variable text instead of msg. It only can’t recognize an unexpected success in a expectedFailure block

Example test methods:

    def test_error(self):
        self.assertEqual(1 / 0, 1)

    def test_fail(self):
        self.assertEqual(2, 1)

    def test_success(self):
        self.assertEqual(1, 1)

Example output:

$ python3 -m unittest test

ERROR: q.MyTest.test_error
     ZeroDivisionError: division by zero
E

FAIL: q.MyTest.test_fail
     AssertionError: 2 != 1
F

OK: q.MyTest.test_success
.
======================================================================
... skipped the usual output from unittest with tracebacks ...
...
Ran 3 tests in 0.001s

FAILED (failures=1, errors=1)

Complete code including expectedFailure decorator example

EDIT: When I updated this solution to Python 3.11, I dropped everything related to old Python < 3.4 and also many minor notes.

Leave a Comment