1

I have the following code to set a faketime during tests.

I'ld like to change the time during a test. That is, the test should start at 9:00 for isntance and then continue as if it is 10:00 .

from __future__ import annotations

import datetime
import logging

import pytest

LOGGER = logging.getLogger(__name__)


@pytest.fixture(params=[datetime.datetime(2020, 12, 25, 17, 5, 55)])
def patch_datetime_now(request, monkeypatch):
    class mydatetime(datetime.datetime):
        @classmethod
        def now(cls):
            return request.param

    class mydate(datetime.date):
        @classmethod
        def today(cls):
            return request.param.date()

    monkeypatch.setattr(datetime, "datetime", mydatetime)
    monkeypatch.setattr(datetime, "date", mydate)


@pytest.mark.usefixtures("patch_datetime_now")
@pytest.mark.parametrize(
    "patch_datetime_now", [(datetime.datetime(2020, 12, 9, 11, 22, 00))], indirect=True
)
def test_update_data():
    fakeTime = datetime.datetime.now()
    # Do some stuff

    # Change the fake time

    # Do some other stuff

How can I change the fake time during the test. The 'datetime' is used inside the code tested, so it's not about changing the "fakeTime" variable contents, but about changing the time returned by the datetime mockup.

Maybe I need to change the mocking method completely, I am just sharing my current code.

le_top
  • 445
  • 3
  • 12
  • Does this answer your question? [How to monkeypatch python's datetime.datetime.now with py.test?](https://stackoverflow.com/questions/20503373/how-to-monkeypatch-pythons-datetime-datetime-now-with-py-test) – MrBean Bremen Mar 21 '22 at 21:40
  • Ok, one of the answers gives an idea: https://stackoverflow.com/a/28073449/6378634 . – le_top Mar 22 '22 at 09:24
  • Mostly [this answer](https://stackoverflow.com/a/28080767/12480730) (freezegun) is used, AFAIK. – MrBean Bremen Mar 22 '22 at 09:38
  • @MrBeanBremen There is no example showing how to change the time during a test. The monkeypatch solution is to add a method to change the time. – le_top Mar 22 '22 at 12:38
  • Maybe I don't understand what you mean, but I mean the examples in the "Context manager" and the "Raw use" sections. – MrBean Bremen Mar 22 '22 at 12:46
  • Ok - this is explained in [freezegun's documentation](http://stevepulec.com/freezegun/) - not in the awswers. – le_top Mar 22 '22 at 13:03
  • Ah yes, this is what I meant - the answer just links it. – MrBean Bremen Mar 22 '22 at 13:17

1 Answers1

0

Following this answer on another question provided by @MrBeanBremen I updated my code like this:

from __future__ import annotations

import datetime
import logging

import pytest

LOGGER = logging.getLogger(__name__)


@pytest.fixture(params=[datetime.datetime(2020, 12, 25, 17, 5, 55)])
def patch_datetime_now(request, monkeypatch):
    def _delta(timedelta=None, **kwargs):
        """ Moves time fwd/bwd by the delta"""
        from datetime import timedelta as td
        if not timedelta:
            timedelta = td(**kwargs)
        request.param += timedelta

    class mydatetime(datetime.datetime):
        @classmethod
        def now(cls):
            return request.param

        @classmethod
        def delta(cls,*args,**kwargs):
            _delta(*args,**kwargs)

    class mydate(datetime.date):
        @classmethod
        def today(cls):
            return request.param.date()

        @classmethod
        def delta(cls,*args,**kwargs):
            _delta(*args,**kwargs)

    monkeypatch.setattr(datetime, "datetime", mydatetime)
    monkeypatch.setattr(datetime, "date", mydate)


@pytest.mark.usefixtures("patch_datetime_now")
@pytest.mark.parametrize(
    "patch_datetime_now", [(datetime.datetime(2020, 12, 9, 11, 22, 00))], indirect=True
)
def test_update_data():
    fakeTime = datetime.datetime.now()
    assert fakeTime ==  datetime.datetime(2020, 12, 9, 11, 22, 00)
    datetime.datetime.delta(hours=1,seconds=10)
    fakeTime = datetime.datetime.now()
    assert fakeTime ==  datetime.datetime(2020, 12, 9, 12, 22, 10)
le_top
  • 445
  • 3
  • 12