Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Is it possible to get the results of a test (i.e. whether all assertions have passed) in a tearDown() method? I'm running Selenium scripts, and I'd like to do some reporting from inside tearDown(), however I don't know if this is possible.

like image 487
Joey Robert Avatar asked Dec 10 '10 23:12

Joey Robert


People also ask

What is teardown method in Python?

Likewise, if a tearDown() method is defined, the test runner will invoke that method after each test. For example you have a test that requires items to exist, or certain state - so you put these actions(creating object instances, initializing db, preparing rules and so on) into the setUp.

How are test failures identified in Python?

If the test fails, an exception will be raised with an explanatory message, and unittest will identify the test case as a failure. Any other exceptions will be treated as errors.

What is a teardown method?

A teardown test case will execute at the end of your test run within a test folder. Teardown test cases are used to perform post test execution actions. For example, a teardown test case can be used to delete test data generated during test execution.

What does Unittest main () do?

Internally, unittest. main() is using a few tricks to figure out the name of the module (source file) that contains the call to main() . It then imports this modules, examines it, gets a list of all classes and functions which could be tests (according the configuration) and then creates a test case for each of them.


1 Answers

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:                     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.

like image 86
hynekcer Avatar answered Sep 21 '22 07:09

hynekcer