Skip to content

Instantly share code, notes, and snippets.

@hynekcer
Last active March 13, 2025 12:03
Show Gist options
  • Save hynekcer/1b0a260ef72dae05fe9611904d7b9675 to your computer and use it in GitHub Desktop.
Save hynekcer/1b0a260ef72dae05fe9611904d7b9675 to your computer and use it in GitHub Desktop.
Getting Python's unittest results in a tearDown() method (my SO answer, question 4414234)
"""Getting Python's unittest results in a tearDown() method
https://stackoverflow.com/questions/4414234/getting-pythons-unittest-results-in-a-teardown-method#39606065
"""
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))
def list2reason(self, exc_list):
if exc_list and exc_list[-1][0] is self:
return exc_list[-1][1]
# demo tests
def test_success(self):
self.assertEqual(1, 1)
def test_fail(self):
self.assertEqual(2, 1)
def test_error(self):
self.assertEqual(1 / 0, 1)
@unittest.expectedFailure
def test_expected_fail(self):
self.assertEqual(2, 1)
@unittest.expectedFailure
def test_expected_error(self):
self.assertEqual(1 / 0, 1)
@unittest.expectedFailure
def test_unexpected_success(self):
self.assertEqual(1, 1)
@johnthacker
Copy link

Note that the Python 3.11 approach doesn't work if the tests are run with pytest and the pytest developers have no no intention of making it work, since the _Outcome is a private attribute. The 3.4 to 3.10 code works fine when pytest is used to run unittest based tests.

@fruch
Copy link

fruch commented Jan 6, 2023

Note that the Python 3.11 approach doesn't work if the tests are run with pytest and the pytest developers have no no intention of making it work, since the _Outcome is a private attribute. The 3.4 to 3.10 code works fine when pytest is used to run unittest based tests.

Why do you need this trickery when using pytest as a runner ? pytest offer much better alternatives to this hack

@johnthacker
Copy link

Why do you need this trickery when using pytest as a runner ? pytest offer much better alternatives to this hack

We don't need it, but with Python 3.4-3.10 the original hack works the same both with and without using pytest.

@yzm157
Copy link

yzm157 commented May 11, 2023

In this way, the results of pass, fail, and error can be obtained, but it is impossible to know whether the use case is skipped. is there any way to know

@sam-ghosh
Copy link

Are you sure this works because I am getting self._outcome.result.error - result does not have error attr or failure attr
image

@hynekcer
Copy link
Author

You can see the comments that one branch is used by Python <= 3.10 and the other by Python >= 3.11.
The used branch works and the other is invalid. You probably evaluate it only in Python <= 3.10 but you should also try it in Python >= 3.11 to can verify the code.

@sam-ghosh
Copy link

sam-ghosh commented Jun 26, 2024

I checked again, and the attribute "error" cannot be found occurs only when using pytest (7.4.4 is my pytest version, also checked for pytest 8.2), your code works with python - m unittest test.py . Any way to fix this for pytest?

image

@hynekcer
Copy link
Author

hynekcer commented Jul 1, 2024

It works also with pytest 7.4.4 or 8.2.2 (your versions) if Python is <= 3.10.x

The package "pytest " is so different from "unittest" that I don't have the energy to start reverse engineering to fix it for fun for Python >= 3.11.

@fluffy-kaiju
Copy link

Thanks! Work perfectly for me 😄
Python 3.11.9

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment