I was surprised to find that pytest-timeout only applies to fixture teardowns if the underlying test succeeds:
import time
import pytest
@pytest.fixture
def bad_fixture():
yield
print("In bad_fixture... sleeping")
time.sleep(5) # Should time out!
print("Didn't time out!")
@pytest.mark.usefixtures("bad_fixture")
def test_timeout1():
print("In test_timeout1... raising an error")
raise ValueError
@pytest.mark.usefixtures("bad_fixture")
def test_timeout2():
print("In test_timeout2...")
When running using pytest --timeout 1, the time.sleep(5) times out in test_timeout2 but runs for the full 5 seconds in test_timeout1.
I expected the fixture to time out in both, and I figure this might be a pytest detail I don't understand. I spent some time tracing through pytest and pytest-timeout code and didn't figure out the answer. For some reason, the pytest_timeout_cancel_timer hook runs at different stages depending on whether the test failed.
Is this a bug? Is there a way to make the timeout apply to fixtures regardless of test status?
As a side-question / request, I'd love if there was a way to make pytest-timeout interrupt at an interval after the timeout, to cancel slow teardown operations that might run after the initial timeout. I think I have some misbehaving fixtures with blocking teardowns, but I'm having trouble locating them. My CI terminates the test job when it hangs, and because I'm using pytest-xdist, it's hard to figure out where a test worker was blocked (print statements don't propagate).
EDIT:
pytest version 8.4.2, also tested 9.1.1
pytest-timeout version 2.4.0
- Running on macOS
- Using the "signal" method
I was surprised to find that
pytest-timeoutonly applies to fixture teardowns if the underlying test succeeds:When running using
pytest --timeout 1, thetime.sleep(5)times out intest_timeout2but runs for the full 5 seconds intest_timeout1.I expected the fixture to time out in both, and I figure this might be a
pytestdetail I don't understand. I spent some time tracing throughpytestandpytest-timeoutcode and didn't figure out the answer. For some reason, thepytest_timeout_cancel_timerhook runs at different stages depending on whether the test failed.Is this a bug? Is there a way to make the timeout apply to fixtures regardless of test status?
As a side-question / request, I'd love if there was a way to make
pytest-timeoutinterrupt at an interval after the timeout, to cancel slow teardown operations that might run after the initial timeout. I think I have some misbehaving fixtures with blocking teardowns, but I'm having trouble locating them. My CI terminates the test job when it hangs, and because I'm usingpytest-xdist, it's hard to figure out where a test worker was blocked (print statements don't propagate).EDIT:
pytestversion 8.4.2, also tested 9.1.1pytest-timeoutversion 2.4.0