Free tools Windows power users keep installed
One-click scans. No signup required.
Use tearDown() to run code after each test method, including one that fails or raises an unexpected exception, provided setUp() completed. To act once after the whole suite, run it from a Python driver and inspect the TestResult returned by the runner. If cleanup must also run when setup fails, register it with addCleanup() after creating the resource, after confirming that your installed unittest2 version supports that API.
Choose where the follow-up should run
| Need | Use | What it can observe |
|---|---|---|
| Run code after each test method | tearDown() |
The test method’s outcome has been recorded before teardown runs. |
| Clean up a resource even if setup later fails | addCleanup(), registered as soon as the resource is created |
Cleanup is associated with the test instance; verify API support in the installed version. |
| Run a report or action once after the suite | Call the suite through a runner in a driver script and inspect its returned result | Failures, errors and overall success recorded by that run. |
| Run a shell or CI step after the test process exits | Sequence commands in the shell or CI job | The process exit status; preserve the test command’s status. |
Run code after each test with tearDown()
Define tearDown(self) on your TestCase for per-test work such as recording diagnostics or releasing state. It runs after a test method fails an assertion or raises an unexpected exception, as long as setUp() completed successfully. It is not a hook that runs once after the test suite.
For example, assuming the installed package exposes the APIs shown:
import unittest2
class ExampleTest(unittest2.TestCase):
def setUp(self):
self.resource = open_resource()
self.addCleanup(self.resource.close)
def test_something(self):
exercise(self.resource)
def tearDown(self):
# Runs after this test method's outcome is recorded,
# provided setUp() completed successfully.
save_per_test_diagnostics()
Replace open_resource(), exercise() and save_per_test_diagnostics() with application-specific functions. The example's cleanup registration is useful when setup may fail after the resource is created; check compatibility before relying on addCleanup() in a legacy installation. Current Python documentation describes cleanup callbacks running after teardown in last-in-first-out order and still running if setup fails. Python's unittest documentation marks API availability by version; those details should not be assumed for an old unittest2 environment.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Scan for outdated or missing drivers - takes under a minute3Repair Windows errors before they cause bigger problems#1 Best Overall
Protect the original failure
If teardown raises, the test result may gain an additional error. Keep follow-up logic defensive: handle expected diagnostic or cleanup exceptions where appropriate, and avoid allowing a secondary failure to hide the test failure you are trying to investigate. Teardown only runs when setup succeeded, so it is not sufficient by itself for resources created partway through a failing setup.
Run code once after the full suite
Load and run the suite in a driver script, then inspect the returned result. This example uses the package's loader and text runner APIs; confirm they match the installed unittest2 release and runtime.
Rank #2
import unittest2
suite = unittest2.TestLoader().discover("tests")
result = unittest2.TextTestRunner(verbosity=2).run(suite)
if result.failures or result.errors:
run_failure_report(result)
Here, failures are assertion failures or explicit test failures; errors are unexpected exceptions. Use either collection when you want action on any unsuccessful test. result.wasSuccessful() answers whether all tests run so far passed. The runner returns the result after execution, so suite-level reporting belongs after run(suite), not in a per-test teardown.
The run_failure_report() function is application-specific. If the process should also exit unsuccessfully when tests fail, make that policy explicit in the driver rather than assuming a reporting function will preserve the test runner's exit behavior.
Run a shell or CI command after tests
If the follow-up is an external command rather than Python code inside the test runner, sequence it in your shell or CI configuration. The unittest2 project documents the unit2 command, including unit2 discover and unit2 -v test_module. For example, a shell construct can run a report only on failure:
unit2 discover || ./collect-test-diagnostics
That simple form can return the status of the diagnostic command instead of the test command. In CI, capture the test exit status, run the follow-up, then return the captured status so a failing test job does not appear successful merely because reporting succeeded. The package documentation describes the command-line entry point, but not a special unittest2 post-failure shell hook.
Check unittest2 and Python compatibility
unittest2 is a backport of features from Python's unittest. Its PyPI project page documents its tested Python versions, the unit2 command, and compatibility limits when mixing unittest2 infrastructure with standard-library loaders, runners or result objects. Check the installed package and Python runtime before copying an example: current standard-library documentation can include APIs unavailable in an older combination.
Python 3.14 documentation, reviewed on 2026-10-04, includes later APIs such as enterContext() and addClassCleanup(); those should not be presumed to exist in legacy environments. The package-specific reference is unittest2 on PyPI. Historical examples can also differ from current behavior; use the documentation corresponding to the runtime and package you actually execute.
Best Value
Troubleshoot common cases
- Teardown did not run: Check whether
setUp()completed. A setup failure preventstearDown()from being called; register resource cleanup immediately after creation if supported. - The follow-up runs after every test, not once: That is the scope of
tearDown(). Move suite-wide reporting to code after the runner returns. - The suite report misses failures: Inspect both
result.failuresandresult.errors; assertion failures and unexpected exceptions are separate categories. - A teardown error obscures the original issue: Make teardown and cleanup resilient, and avoid raising a new exception while collecting diagnostics.
- A method or import is unavailable: Verify the installed Python and
unittest2versions, then check the version annotation for the API. Do not infer legacy support from current Python documentation. - CI reports success after tests failed: Preserve and return the test process's exit status after running any failure-reporting step.
Or skip the browser setup
If the follow-up you need is a website screenshot for a report, ScreenshotNeo offers a screenshot API and MCP server. A single GET request can return an image or PDF; its API documentation is at ScreenshotNeo docs.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Cookie banners are accepted and removed before capture, along with supported newsletter popups and chat widgets; those steps can be turned off. Bot checks, blank pages, failed loads and cache hits are not billed, and response headers report the page verdict and billing status. Its MCP server provides screenshot tools for AI agents. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000.
Sign up free for ScreenshotNeo.
Frequently Asked Questions
What does unittest2 provide for running tests from the command line?
The project documents the unit2 script, including unit2 discover and unit2 -v test_module.
Can teardown tell whether its test failed?
The result is recorded before teardown runs, but the examples here do not add custom result-inspection logic inside tearDown(). For actions based on the completed suite result, inspect the runner's returned TestResult.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




