Skip to content

Commit 078d793

Browse files
committed
Add new fixed_datetime and with_fixed_datetime functions to testing.py
1 parent f4f9426 commit 078d793

File tree

3 files changed

+135
-3
lines changed

3 files changed

+135
-3
lines changed

domdf_python_tools/testing.py

Lines changed: 91 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
import os
5555
import random
5656
import sys
57+
from contextlib import contextmanager
5758
from functools import lru_cache
5859
from pathlib import Path
5960
from textwrap import dedent
@@ -62,6 +63,7 @@
6263
# 3rd party
6364
import pytest # nodep
6465
from _pytest.mark import MarkDecorator # nodep
66+
from pytest import MonkeyPatch # nodep
6567
from pytest_regressions.file_regression import FileRegressionFixture # nodep
6668

6769
# this package
@@ -98,7 +100,9 @@
98100
"tmp_pathplus",
99101
"whitespace",
100102
"whitespace_perms",
101-
"whitespace_perms_list"
103+
"whitespace_perms_list",
104+
"fixed_datetime",
105+
"with_fixed_datetime",
102106
]
103107

104108
MarkDecorator.__module__ = "_pytest.mark"
@@ -558,3 +562,89 @@ def check_file_output(
558562
extension = "._py_"
559563

560564
return check_file_regression(data, file_regression, extension, newline=newline, **kwargs)
565+
566+
567+
@pytest.fixture()
568+
def fixed_datetime(monkeypatch):
569+
"""
570+
Pytest fixture to pretend the current datetime is 2:20 AM on 13th October 2020.
571+
572+
.. versionadded:: 2.2.0
573+
574+
.. seealso:: The :func:`with_fixed_datetime` contextmanager.
575+
576+
.. attention::
577+
578+
The monkeypatching only works when datetime is used and imported like:
579+
580+
.. code-block:: python
581+
582+
import datetime
583+
print(datetime.datetime.now())
584+
585+
Using ``from datetime import datetime`` won't work.
586+
"""
587+
588+
with with_fixed_datetime(datetime.datetime(2020, 10, 13, 2, 20)):
589+
yield
590+
591+
592+
@contextmanager
593+
def with_fixed_datetime(fixed_datetime: datetime.datetime):
594+
"""
595+
Context manager to set a fixed datetime for the duration of the ``with`` block.
596+
597+
.. versionadded:: 2.2.0
598+
599+
:param fixed_datetime:
600+
601+
.. seealso:: The :fixture:`fixed_datetime` fixture.
602+
603+
.. attention::
604+
605+
The monkeypatching only works when datetime is used and imported like:
606+
607+
.. code-block:: python
608+
609+
import datetime
610+
print(datetime.datetime.now())
611+
612+
Using ``from datetime import datetime`` won't work.
613+
"""
614+
615+
class D(datetime.date):
616+
617+
@classmethod
618+
def today(cls):
619+
return datetime.date(
620+
fixed_datetime.year,
621+
fixed_datetime.month,
622+
fixed_datetime.day,
623+
)
624+
625+
class DT(datetime.datetime):
626+
627+
@classmethod
628+
def today(cls):
629+
return datetime.datetime(
630+
fixed_datetime.year,
631+
fixed_datetime.month,
632+
fixed_datetime.day,
633+
)
634+
635+
@classmethod
636+
def now(cls, tz=None):
637+
return datetime.datetime.fromtimestamp(fixed_datetime.timestamp())
638+
639+
D.__name__ = "date"
640+
D.__qualname__ = "date"
641+
DT.__qualname__ = "datetime"
642+
DT.__name__ = "datetime"
643+
D.__module__ = "datetime"
644+
DT.__module__ = "datetime"
645+
646+
with MonkeyPatch.context() as monkeypatch:
647+
monkeypatch.setattr(datetime, "date", D)
648+
monkeypatch.setattr(datetime, "datetime", DT)
649+
650+
yield

repo_helper.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ extras_require:
3030
dates:
3131
- pytz>=2019.1
3232
testing:
33-
- pytest>=6.0.0
33+
- pytest>=6.2.0
3434
- pytest-regressions>=2.0.2
3535

3636
conda_extras:

tests/test_testing.py

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# stdlib
2+
import datetime
23
import platform
34
import random
45
import re
@@ -20,7 +21,8 @@
2021
only_macos,
2122
only_pypy,
2223
only_version,
23-
only_windows
24+
only_windows,
25+
with_fixed_datetime
2426
)
2527
from domdf_python_tools.utils import strtobool
2628

@@ -221,3 +223,43 @@ def test_check_file_output(tmp_pathplus, file_regression: FileRegressionFixture)
221223

222224
(tmp_pathplus / "file.txt").write_text("Success!")
223225
check_file_output(tmp_pathplus / "file.txt", file_regression)
226+
227+
228+
def test_fixed_datetime(fixed_datetime):
229+
assert datetime.datetime.today() == datetime.datetime(2020, 10, 13)
230+
assert datetime.datetime.now() == datetime.datetime(2020, 10, 13, 2, 20)
231+
232+
assert datetime.datetime.__name__ == "datetime"
233+
assert datetime.datetime.__qualname__ == "datetime"
234+
assert datetime.datetime.__module__ == "datetime"
235+
236+
assert datetime.date.today() == datetime.date(2020, 10, 13)
237+
238+
assert datetime.date.__name__ == "date"
239+
assert datetime.date.__qualname__ == "date"
240+
assert datetime.date.__module__ == "datetime"
241+
242+
243+
@pytest.mark.parametrize(
244+
"fake_datetime, expected_date",
245+
[
246+
pytest.param(datetime.datetime(2020, 10, 13, 2, 20), datetime.datetime(2020, 10, 13), id='0'),
247+
pytest.param(datetime.datetime(2020, 7, 4, 10, 00), datetime.datetime(2020, 7, 4), id='1'),
248+
]
249+
)
250+
def test_with_fixed_datetime(fake_datetime, expected_date):
251+
252+
with with_fixed_datetime(fake_datetime):
253+
assert datetime.datetime.today() == expected_date
254+
assert datetime.datetime.now() == fake_datetime
255+
256+
assert datetime.datetime.__name__ == "datetime"
257+
assert datetime.datetime.__qualname__ == "datetime"
258+
assert datetime.datetime.__module__ == "datetime"
259+
260+
assert datetime.date.today() == expected_date
261+
assert isinstance(datetime.date.today(), datetime.date)
262+
263+
assert datetime.date.__name__ == "date"
264+
assert datetime.date.__qualname__ == "date"
265+
assert datetime.date.__module__ == "datetime"

0 commit comments

Comments
 (0)