pytest-timeout
pytest-timeout is an actively maintained pytest plugin designed to automatically abort excessively long-running or hanging tests. It helps in maintaining efficient test suites by enforcing timeout limits at various levels (global, session, per-test) and provides different methods to terminate tests. The current version is 2.4.0 and it is part of the pytest-dev organization, implying regular updates and maintenance.
Warnings
- breaking Minimum `pytest` version has increased. For `pytest-timeout` versions 2.2.0 and later, `pytest>=7.0.0` is required. Ensure your `pytest` installation is up-to-date to avoid compatibility issues. Python 3.7+ is required for version 2.4.0.
- gotcha The plugin offers two timeout methods: 'signal' (default on supported systems) and 'thread'. The 'signal' method (using SIGALRM) is generally more efficient but can interfere with code under test that also uses SIGALRM. The 'thread' method is more portable and reliable but incurs more overhead and can prevent other `pytest` features (like JUnit XML or fixture teardown) from completing normally because it terminates the entire process.
- gotcha Session timeouts (`--session-timeout`) are 'cooperative'. They check the session time at the end of each test function and stop *further* tests from running if the timeout is exceeded. They will *not* interrupt a test currently in progress. To ensure a test-in-progress is interrupted, a per-function timeout must also be set.
- gotcha By default, timeouts apply to the entire test lifecycle, including fixture setup and teardown. If your fixtures are long-running, they can cause tests to time out prematurely.
- gotcha By default, `pytest-timeout` attempts to detect when a debugger (like pdb or PyCharm's debugger) is active and disables timeouts to prevent interruption during debugging sessions. This behavior can be explicitly disabled.
Install
-
pip install pytest-timeout
Imports
- pytest.mark.timeout
import pytest @pytest.mark.timeout(300) def test_example(): pass
Quickstart
import pytest
import time
import os
# Example pytest.ini content (can be placed in a file named pytest.ini)
# [pytest]
# timeout = 5
# Or set via environment variable (e.g., in CI/CD)
# export PYTEST_TIMEOUT=10
# A test that should pass within the global timeout (if set to > 1)
def test_fast_operation():
time.sleep(1) # Simulates a quick operation
assert True
# A test with a specific timeout marker, overriding global settings
@pytest.mark.timeout(os.environ.get('PYTEST_LONG_TIMEOUT', 20))
def test_long_running_operation():
time.sleep(15) # Simulates a potentially long operation
assert True
# A test designed to time out if default or global timeout is low
@pytest.mark.timeout(2)
def test_should_timeout():
time.sleep(3) # This will exceed the 2-second mark
assert False, "Should not reach here if timeout works"
# To run these tests:
# 1. Save as a Python file (e.g., test_timeouts.py)
# 2. Run from your terminal: pytest test_timeouts.py
# (or pytest test_timeouts.py --timeout=5 to set a global CLI timeout)