Pytest Timeouts Plugin
pytest-timeouts is a Linux-only Pytest plugin (version 1.2.1) designed to precisely control the duration of various test case execution phases: setup, execution, and teardown. It's distinct from the `pytest-timeout` plugin and is specifically tailored for scenarios requiring SIGALRM-based test interruption on Linux systems. Releases are infrequent but active.
Warnings
- breaking This plugin is explicitly 'Linux-only'. It relies on the SIGALRM signal, which is not reliably available or behaves differently on other operating systems like macOS or Windows. It will not function as expected on non-Linux platforms.
- gotcha The `pytest-timeouts` plugin has a fixed order of precedence for applying timeout settings: command-line options (`opts`) > markers (`markers`) > `pytest.ini` (`ini`). This order can be customized or disabled using the `--timeouts-order` command-line option, e.g., `--timeouts-order oi` to prioritize `opts` then `ini` and disable markers.
- gotcha When a test is terminated due to a timeout, especially with hard termination methods (like `os._exit()` which is often used), it may result in an abrupt exit without proper fixture teardown, incomplete JUnit XML output, or other post-test processing. While debugging information is usually preserved, be aware of these side-effects.
- deprecated Version 1.2.1 fixed a `PyTest get_marker warning` that specifically affected `pytest 3.10.X`. This indicates potential compatibility issues or warnings when using `pytest-timeouts` with specific `pytest` versions, particularly around how markers are accessed. Newer `pytest` versions generally prefer `request.node.get_closest_marker`.
- gotcha This plugin (`pytest-timeouts`) is distinct from the more widely known `pytest-timeout` plugin. `pytest-timeouts` is specifically designed for Linux and focuses on granular phase timeouts (setup, execution, teardown) using `SIGALRM`, whereas `pytest-timeout` offers broader OS support and different timeout mechanisms.
Install
-
pip install pytest-timeouts
Imports
- pytest.mark.<timeout_type>
import pytest @pytest.mark.execution_timeout(1.5) def test_something(): ...
Quickstart
import time
import pytest
# Configure global timeouts in pytest.ini (optional):
# [pytest]
# setup_timeout = 0.3
# execution_timeout = 0.5
# teardown_timeout = 0.4
@pytest.mark.setup_timeout(0.3)
@pytest.mark.execution_timeout(0.5)
@pytest.mark.teardown_timeout(0.4)
def test_timeout_phases():
print("\nStarting setup (simulated)")
time.sleep(0.1) # Simulate setup
print("Starting execution (simulated)")
time.sleep(0.6) # This will exceed execution_timeout(0.5)
print("Starting teardown (simulated)")
time.sleep(0.1) # Simulate teardown
def test_no_timeout():
print("\nRunning test without explicit timeouts")
time.sleep(0.1)
# To run this test, save as test_example.py and execute:
# pytest -v test_example.py