Skip to content

Commit

Permalink
docs + config setting support + test mod
Browse files Browse the repository at this point in the history
  • Loading branch information
okken authored and flub committed Mar 7, 2024
1 parent 063f077 commit 325b40c
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 11 deletions.
34 changes: 34 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,39 @@ function:
pytest.fail("+++ Timeout +++")
Session Timeout
===============

The above mentioned timeouts are all per test function. You can also set a
session timeout in seconds. The following example shows a session timeout
of 10 minutes (600 seconds)::

pytest --session-timeout=600

You can also set the session timeout the `pytest configuration file`__
using the ``session_timeout`` option:

.. code:: ini
[pytest]
session_timeout = 600
Friendly timeouts
-----------------

Session timeouts are "friendly" timeouts. The plugin checks the session time at the end of
each test function, and stops further tests from running if the session timeout is exceeded.

Combining session and function
------------------------------

It works fine to combine both session and function timeouts.
For example, to limit test functions to 5 seconds and the full session to 100 seconds::

pytest --timeout=5 --session-timeout=100


Changelog
=========

Expand All @@ -353,6 +386,7 @@ Unreleased
This change also switches all output from ``sys.stderr`` to ``sys.stdout``.
Thanks Pedro Algarvio.
- Pytest 7.0.0 is now the minimum supported version. Thanks Pedro Algarvio.
- Add ``--session-timeout`` option and ``session_timeout`` setting.

2.2.0
-----
Expand Down
18 changes: 13 additions & 5 deletions pytest_timeout.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

__all__ = ("is_debugging", "Settings")
SESSION_TIMEOUT_KEY = pytest.StashKey[float]()
SESSION_EXPIRE_KEY = pytest.StashKey[float]()


HAVE_SIGALRM = hasattr(signal, "SIGALRM")
Expand Down Expand Up @@ -104,6 +105,7 @@ def pytest_addoption(parser):
type="bool",
default=False,
)
parser.addini("session_timeout", SESSION_TIMEOUT_DESC)


class TimeoutHooks:
Expand Down Expand Up @@ -159,12 +161,18 @@ def pytest_configure(config):
config._env_timeout_func_only = settings.func_only
config._env_timeout_disable_debugger_detection = settings.disable_debugger_detection

timeout = config.getoption("--session-timeout")
timeout = config.getoption("session_timeout")
if timeout is None:
ini = config.getini("session_timeout")
if ini:
timeout = _validate_timeout(config.getini("session_timeout"), "config file")
if timeout is not None:
expire_time = time.time() + timeout
else:
expire_time = 0
config.stash[SESSION_TIMEOUT_KEY] = expire_time
timeout = 0
config.stash[SESSION_TIMEOUT_KEY] = timeout
config.stash[SESSION_EXPIRE_KEY] = expire_time


@pytest.hookimpl(hookwrapper=True)
Expand All @@ -185,9 +193,9 @@ def pytest_runtest_protocol(item):
hooks.pytest_timeout_cancel_timer(item=item)

# check session timeout
expire_time = item.session.config.stash[SESSION_TIMEOUT_KEY]
expire_time = item.session.config.stash[SESSION_EXPIRE_KEY]
if expire_time and (expire_time < time.time()):
timeout = item.session.config.getoption("--session-timeout")
timeout = item.session.config.stash[SESSION_TIMEOUT_KEY]
item.session.shouldfail = f"session-timeout: {timeout} sec exceeded"


Expand Down Expand Up @@ -223,7 +231,7 @@ def pytest_report_header(config):
)
)

session_timeout = config.getoption("--session-timeout")
session_timeout = config.getoption("session_timeout")
if session_timeout:
timeout_header.append("session timeout: %ss" % session_timeout)
if timeout_header:
Expand Down
35 changes: 29 additions & 6 deletions test_pytest_timeout.py
Original file line number Diff line number Diff line change
Expand Up @@ -623,17 +623,40 @@ def test_session_timeout(pytester):
@pytest.fixture()
def slow_setup_and_teardown():
time.sleep(0.5)
time.sleep(1)
yield
time.sleep(0.5)
time.sleep(1)
def test_one(slow_setup_and_teardown):
time.sleep(0.5)
time.sleep(1)
def test_two(slow_setup_and_teardown):
time.sleep(0.5)
time.sleep(1)
"""
)
result = pytester.runpytest_subprocess("--session-timeout", "1.25")
result.stdout.fnmatch_lines(["*!! session-timeout: 1.25 sec exceeded !!!*"])
result = pytester.runpytest_subprocess("--session-timeout", "2")
result.stdout.fnmatch_lines(["*!! session-timeout: 2.0 sec exceeded !!!*"])
result.assert_outcomes(passed=1)


def test_ini_session_timeout(pytester):
pytester.makepyfile(
"""
import time
def test_one():
time.sleep(2)
def test_two():
time.sleep(2)
"""
)
pytester.makeini(
"""
[pytest]
session_timeout = 1
"""
)
result = pytester.runpytest_subprocess()
result.stdout.fnmatch_lines(["*!! session-timeout: 1.0 sec exceeded !!!*"])
result.assert_outcomes(passed=1)

0 comments on commit 325b40c

Please sign in to comment.