-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
17 changed files
with
971 additions
and
156 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,5 +17,8 @@ | |
], | ||
"lockFileMaintenance": { | ||
"enabled": true, | ||
}, | ||
"pre-commit": { | ||
"enabled": true | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,122 +1,8 @@ | ||
pytest-time | ||
=========== | ||
|
||
The pytest-time plugin extends pytest to control ``time`` — the built-in Python | ||
module, not the concept within the universe. | ||
The pytest-time plugin extends pytest to control ``time`` — the built-in Python module, | ||
not the concept within the universe. | ||
|
||
.. image:: https://github.com/lengau/pytest-time/actions/workflows/tests.yaml/badge.svg | ||
:target: https://github.com/lengau/pytest-time/actions/workflows/tests.yaml | ||
|
||
Fixtures | ||
-------- | ||
|
||
Pytest-time offers several fixtures for use in your projects, depending on your particular needs. | ||
|
||
Instant Sleep | ||
~~~~~~~~~~~~~ | ||
|
||
The ``instant_sleep`` fixture is the most basic wrapper and is designed to be used at any scope. It monkeypatches the built-in ``time`` module to be chronologically consistent while not actually sleeping when running ``time.sleep``. This includes modifying the behaviour of ``time.time()``, ``time.monotonic()`` and their nanosecond counterparts to include the additional delay expected after sleeping. | ||
|
||
A basic use of ``instant_sleep`` is shown below: | ||
|
||
.. code:: python | ||
import time | ||
import pytest | ||
@pytest.mark.parametrize("sleep_time", [1, 10, 100]) | ||
@pytest.mark.usefixtures("instant_sleep") | ||
def test_instant_sleep(sleep_time): | ||
start_time = time.time() | ||
start_monotonic = time.monotonic() | ||
time.sleep(sleep_time) | ||
assert time.time() >= start_time + sleep_time | ||
assert time.monotonic() >= start_monotonic + sleep_time | ||
This code will behave almost identically with and without the ``instant_sleep`` fixture in use. To demonstrate, let's time this file with the fixture enabled... | ||
|
||
.. code:: text | ||
$ time pytest test_instant_sleep.py | ||
=========== test session starts =========== | ||
platform linux -- Python 3.11.4, pytest-7.3.1, pluggy-1.0.0 | ||
rootdir: /home/lengau/Projects/pytest-time | ||
configfile: pyproject.toml | ||
plugins: check-2.1.5, mock-3.10.0, hypothesis-6.78.2, time-0.2.1.dev3+ga0d3b98.d20230624, cov-4.1.0 | ||
collected 3 items | ||
test_instant_sleep.py ... [100%] | ||
=========== 3 passed in 0.01s =========== | ||
real 0m0.276s | ||
user 0m0.240s | ||
sys 0m0.025s | ||
and disabled: | ||
|
||
.. code:: text | ||
$ time pytest test_instant_sleep_no_fixture.py | ||
=========== test session starts =========== | ||
platform linux -- Python 3.11.4, pytest-7.3.1, pluggy-1.0.0 | ||
rootdir: /home/lengau/Projects/pytest-time | ||
configfile: pyproject.toml | ||
plugins: check-2.1.5, mock-3.10.0, hypothesis-6.78.2, time-0.2.1.dev3+ga0d3b98.d20230624, cov-4.1.0 | ||
collected 3 items | ||
test_instant_sleep_no_fixture.py ... [100%] | ||
=========== 3 passed in 111.01s (0:01:51) =========== | ||
real 1m51.354s | ||
user 0m0.250s | ||
sys 0m0.020s | ||
The sleep is, for practical purposes, essentially instant. And yet, the ``time`` module still acts as though the appropriate time has passed. | ||
|
||
Recording Time Calls | ||
~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
Pytest-time also provides ``mock_time``, a fixture that wraps several ``time`` functions in Mock objects but still runs the real calls. This is useful if you need to ensure that certain calls occurred, etc. The fixture will provide Mock objects for inspection in tests: | ||
|
||
.. code:: python | ||
import time | ||
def test_mock_time(mock_time): | ||
start_time = time.time() | ||
start_monotonic = time.monotonic() | ||
time.sleep(1) # Actually sleeps for a second | ||
assert time.time() >= start_time + 1 | ||
assert time.monotonic() >= start_monotonic + 1 | ||
mock_time.sleep.assert_called_once_with(1) | ||
assert len(mock_time.time.mock_calls) == 2 | ||
assert len(mock_time.monotonic.mock_calls) == 2 | ||
Mocking a Powernap | ||
~~~~~~~~~~~~~~~~~~ | ||
|
||
The two above are combined for you in the ``mock_instant_sleep`` fixture. This fixture replaces the relevant ``time`` functions as in the ``instant_sleep`` fixture, but also provides mock wrappers around those functions, allowing for recording time. | ||
|
||
.. code:: python | ||
import time | ||
def test_mock_instant_sleep(mock_instant_sleep): | ||
start_time = time.time() | ||
start_monotonic = time.monotonic() | ||
time.sleep(86400) # Doesn't sleep | ||
assert time.time() >= start_time + 86400 | ||
assert time.monotonic() >= start_monotonic + 86400 | ||
mock_instant_sleep.sleep.assert_called_once_with(86400) | ||
assert len(mock_instant_sleep.time.mock_calls) == 2 | ||
assert len(mock_instant_sleep.monotonic.mock_calls) == 2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# Minimal makefile for Sphinx documentation | ||
# | ||
|
||
# You can set these variables from the command line, and also | ||
# from the environment for the first two. | ||
SPHINXOPTS ?= | ||
SPHINXBUILD ?= sphinx-build | ||
SOURCEDIR = . | ||
BUILDDIR = _build | ||
|
||
# Put it first so that "make" without argument is like "make help". | ||
help: | ||
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) | ||
|
||
.PHONY: help Makefile | ||
|
||
# Catch-all target: route all unknown targets to Sphinx using the new | ||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). | ||
%: Makefile | ||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) | ||
|
||
auto: | ||
sphinx-autobuild --ignore '*.kate-swp' "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
# Configuration file for the Sphinx documentation builder. | ||
# | ||
# For the full list of built-in configuration values, see the documentation: | ||
# https://www.sphinx-doc.org/en/master/usage/configuration.html | ||
|
||
# -- Project information ----------------------------------------------------- | ||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information | ||
|
||
project = 'pytest-time' | ||
copyright = '2025, Alex Lowe' | ||
author = 'Alex Lowe' | ||
|
||
# -- General configuration --------------------------------------------------- | ||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration | ||
|
||
extensions = [ | ||
'sphinx.ext.autodoc', | ||
'sphinx.ext.intersphinx', | ||
'sphinx.ext.coverage', | ||
'sphinx.ext.viewcode', | ||
] | ||
|
||
templates_path = ['_templates'] | ||
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store', '.kate-swp'] | ||
|
||
|
||
|
||
# -- Options for HTML output ------------------------------------------------- | ||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output | ||
|
||
html_theme = 'furo' | ||
html_static_path = ['_static'] | ||
|
||
# -- Options for intersphinx extension --------------------------------------- | ||
# https://www.sphinx-doc.org/en/master/usage/extensions/intersphinx.html#configuration | ||
|
||
intersphinx_mapping = { | ||
'python': ('https://docs.python.org/3', None), | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
.. | ||
pytest-time documentation master file, created by | ||
sphinx-quickstart on Sun Jan 19 17:56:54 2025. | ||
You can adapt this file completely to your liking, but it should at least | ||
contain the root `toctree` directive. | ||
``pytest-time`` | ||
=============== | ||
|
||
.. toctree:: | ||
:maxdepth: 2 | ||
:caption: Contents: | ||
|
||
reference/index | ||
|
||
``pytest-time`` is a pytest extension for controlling Python's built-in | ||
:external+python:doc:`time <library/time>` module. | ||
|
||
Indices and tables | ||
================== | ||
|
||
- :ref:`genindex` | ||
- :ref:`modindex` | ||
- :ref:`search` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
Reference | ||
========= | ||
|
||
.. toctree:: | ||
:maxdepth: 2 | ||
|
||
real_time | ||
instant_sleep | ||
mock_time |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
Instant sleep | ||
============= | ||
|
||
The ``instant_sleep`` fixture is the most basic wrapper and is designed to be used at | ||
any scope. It monkeypatches the built-in ``time`` module to be chronologically | ||
consistent while not actually sleeping when running ``time.sleep``. This includes | ||
modifying the behaviour of ``time.time()``, ``time.monotonic()`` and their nanosecond | ||
counterparts to include the additional delay expected after sleeping. | ||
|
||
A basic use of ``instant_sleep`` is shown below: | ||
|
||
.. code-block:: python | ||
import time | ||
import pytest | ||
@pytest.mark.parametrize("sleep_time", [1, 10, 100]) | ||
@pytest.mark.usefixtures("instant_sleep") | ||
def test_instant_sleep(sleep_time): | ||
start_time = time.time() | ||
start_monotonic = time.monotonic() | ||
time.sleep(sleep_time) | ||
assert time.time() >= start_time + sleep_time | ||
assert time.monotonic() >= start_monotonic + sleep_time | ||
This code will behave almost identically with and without the ``instant_sleep`` fixture | ||
in use. To demonstrate, let's time this file with the fixture enabled... | ||
|
||
.. code-block:: text | ||
$ time pytest test_instant_sleep.py | ||
=========== test session starts =========== | ||
platform linux -- Python 3.11.4, pytest-7.3.1, pluggy-1.0.0 | ||
rootdir: /home/lengau/Projects/pytest-time | ||
configfile: pyproject.toml | ||
plugins: check-2.1.5, mock-3.10.0, hypothesis-6.78.2, time-0.2.1.dev3+ga0d3b98.d20230624, cov-4.1.0 | ||
collected 3 items | ||
test_instant_sleep.py ... [100%] | ||
=========== 3 passed in 0.01s =========== | ||
real 0m0.276s | ||
user 0m0.240s | ||
sys 0m0.025s | ||
and disabled: | ||
|
||
.. code-block:: text | ||
$ time pytest test_instant_sleep_no_fixture.py | ||
=========== test session starts =========== | ||
platform linux -- Python 3.11.4, pytest-7.3.1, pluggy-1.0.0 | ||
rootdir: /home/lengau/Projects/pytest-time | ||
configfile: pyproject.toml | ||
plugins: check-2.1.5, mock-3.10.0, hypothesis-6.78.2, time-0.2.1.dev3+ga0d3b98.d20230624, cov-4.1.0 | ||
collected 3 items | ||
test_instant_sleep_no_fixture.py ... [100%] | ||
=========== 3 passed in 111.01s (0:01:51) =========== | ||
real 1m51.354s | ||
user 0m0.250s | ||
sys 0m0.020s | ||
The sleep is, for practical purposes, essentially instant. And yet, the ``time`` module | ||
still acts as though the appropriate time has passed. | ||
|
||
.. autofunction:: pytest_time.instant_sleep |
Oops, something went wrong.