pytest-threadleak
pytest-threadleak is a pytest plugin that automatically detects non-daemon thread leaks after tests complete. It helps identify when tests leave background threads running, which can cause resource exhaustion or unexpected behavior. The current version is 0.5.0, and it is maintained with releases as needed for bug fixes or new features.
Common errors
-
pytest.FixtureLookupError: fixture 'threadleak' not found
cause The pytest-threadleak plugin is not installed, or pytest cannot find it in the current environment.fixEnsure `pytest-threadleak` is installed in the same Python environment where you are running pytest: `pip install pytest-threadleak`. -
Failed: ThreadLeakError: The following threads were still running after the test: ['<Thread(Thread-1, started 123456789)>']
cause A non-daemon thread was spawned during the test and was still active when the test completed. This is the core functionality of the plugin detecting a leak.fixIdentify the code spawning the listed thread(s) and ensure they are either daemonized (if background processing) or properly joined/terminated before the test function finishes. If it's an expected background thread, consider adding its name pattern to `threadleak_thread_name_patterns_to_ignore` in `pytest.ini`.
Warnings
- breaking Python 2 support was dropped in version 0.3.0. Users on Python 2 must use an older version.
- gotcha pytest-threadleak only detects threads that are *still running* and are *not daemon threads* after a test. Threads that complete and join successfully before the test ends will not be flagged. Daemon threads are also ignored by default.
- gotcha If tests fail with `ThreadLeakError` for threads that are part of standard libraries or external packages (e.g., from `requests` or `concurrent.futures`), these threads might need to be explicitly ignored.
Install
-
pip install pytest-threadleak pytest
Imports
- threadleak
from pytest_threadleak import threadleak
def test_something(threadleak): ...
Quickstart
import threading
import time
# test_my_app.py
def test_my_function_no_leak(threadleak):
"""
This test uses the 'threadleak' fixture to ensure no new
non-daemon threads are left running after the test completes.
This specific test should pass cleanly.
"""
def do_something_brief():
time.sleep(0.01)
t = threading.Thread(target=do_something_brief)
t.start()
t.join() # Ensure the thread finishes before the test does
# To run this test:
# pip install pytest-threadleak pytest
# pytest test_my_app.py
# To observe a leak (uncomment and run):
# def test_my_function_with_leak(threadleak):
# """
# This test will intentionally leave a non-daemon thread running,
# causing pytest-threadleak to report a ThreadLeakError.
# """
# def infinite_loop():
# while True:
# time.sleep(0.1)
#
# threading.Thread(target=infinite_loop).start()