3

Is there a way to assert that a Pytest test case has failed due to a pytest timeout? I want to run a longevity test that I expect to run without issue, until a pytest timeout is encountered. I annotate the test with @pytest.mark.timeout(6000)to override the default pytest timeout, and when the 6000 second timeout is encountered, the test fails with E Failed: Timeout >6000.0s.

I've tried adding with pytest.raises(pytest.TimeoutExpired) to my test to catch the eventual timeout, but that doesn't seem to do the trick. Is there a way to properly catch the timeout raised by pytest?

Dave
  • 1,480
  • 3
  • 16
  • 26

1 Answers1

5

Unfortunately, the pytest-timeout plugin, which provides the @pytest.mark.timeout marker, does not offer the means to catch the timeout (source for reference).

You may find more luck using a library that offers timeout functionality as a context manager, such as the one from Thomas Ahle's answer

import signal

class Timeout:
    def __init__(self, seconds=1, error_message='Timeout'):
        self.seconds = seconds
        self.error_message = error_message
    def handle_timeout(self, signum, frame):
        raise TimeoutError(self.error_message)
    def __enter__(self):
        signal.signal(signal.SIGALRM, self.handle_timeout)
        signal.alarm(self.seconds)
    def __exit__(self, type, value, traceback):
        signal.alarm(0)

def test_it_doesnt_succeed():
    try:
        with Timeout(seconds=6):
            do_the_thing()
    except TimeoutError:
        pass
    else:
        raise AssertionError('Expected the thing to timeout!')
theY4Kman
  • 5,572
  • 2
  • 32
  • 38
  • 2
    To add, it does not appear that there are currently any plans to add an exception feature per [closed issue](https://github.com/pytest-dev/pytest-timeout/issues/38). – fragapanagos Mar 17 '21 at 05:38