diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 3178027..6c006af 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -2,6 +2,10 @@ Changelog ========= +* Add ``shift()`` method to the ``time_machine`` pytest fixture. + + Thanks to Stefaan Lippens in `PR 312 `__. + * Mock ``time.monotonic()`` and ``time.monotonic_ns()``. They return the values of ``time.time()`` and ``time.time_ns()`` respectively, rather than real monotonic clocks. diff --git a/README.rst b/README.rst index 020c930..755325c 100644 --- a/README.rst +++ b/README.rst @@ -297,7 +297,7 @@ pytest plugin ------------- time-machine also works as a pytest plugin. -It provides a function-scoped fixture called ``time_machine`` that has one method, ``move_to()``, which has the same signature as ``Coordinates.move_to()``. +It provides a function-scoped fixture called ``time_machine`` with methods ``move_to()`` and ``shift()``, which have the same signature as their equivalents in ``Coordinates``. This can be used to mock your test at different points in time and will automatically be un-mock when the test is torn down. For example: @@ -316,6 +316,10 @@ For example: assert dt.date.today().isoformat() == "2015-10-21" + time_machine.shift(dt.timedelta(days=1)) + + assert dt.date.today().isoformat() == "2015-10-22" + If you are using pytest test classes, you can apply the fixture to all test methods in a class by adding an autouse fixture: .. code-block:: python diff --git a/src/time_machine/__init__.py b/src/time_machine/__init__.py index e7ce191..c0d6bda 100644 --- a/src/time_machine/__init__.py +++ b/src/time_machine/__init__.py @@ -437,6 +437,14 @@ def move_to( assert self.coordinates is not None self.coordinates.move_to(destination, tick=tick) + def shift(self, delta: dt.timedelta | int | float) -> None: + if self.traveller is None: + raise RuntimeError( + "Initialize time_machine with move_to() before using shift()." + ) + assert self.coordinates is not None + self.coordinates.shift(delta=delta) + def stop(self) -> None: if self.traveller is not None: self.traveller.stop() diff --git a/tests/test_time_machine.py b/tests/test_time_machine.py index 5528b41..9736be4 100644 --- a/tests/test_time_machine.py +++ b/tests/test_time_machine.py @@ -717,7 +717,7 @@ def test_fixture_used_tick_true(time_machine): assert original < time.time() < EPOCH + 10.0 -def test_fixture_used_twice(time_machine): +def test_fixture_move_to_twice(time_machine): time_machine.move_to(EPOCH) assert time.time() == EPOCH @@ -725,6 +725,22 @@ def test_fixture_used_twice(time_machine): assert time.time() == EPOCH_PLUS_ONE_YEAR +def test_fixture_move_to_and_shift(time_machine): + time_machine.move_to(EPOCH, tick=False) + assert time.time() == EPOCH + time_machine.shift(100) + assert time.time() == EPOCH + 100 + + +def test_fixture_shift_without_move_to(time_machine): + with pytest.raises(RuntimeError) as excinfo: + time_machine.shift(100) + + assert excinfo.value.args == ( + "Initialize time_machine with move_to() before using shift().", + ) + + # escape hatch tests