userver
C++ Async Framework
Toggle main menu visibility
Loading...
Searching...
No Matches
mocked_time.py
1
import
datetime
2
3
import
dateutil.parser
4
import
pytest
5
6
from
testsuite
import
utils
7
from
testsuite.utils
import
traceback
8
9
MOCK_TIME_DISABLED_MESSAGE = (
10
'Mock time is disabled. Use @pytest.mark.now to enable mock '
11
'time for a particular test'
12
)
13
14
UTC = datetime.timezone.utc
15
16
17
class
BaseError
(Exception):
18
"""Base class for errors in this module"""
19
20
21
class
DisabledUsageError
(
BaseError
):
22
"""Raised when attempting to use a disabled feature"""
23
24
25
__tracebackhide__ = traceback.hide(BaseError)
26
27
28
class
MockedTime
:
29
def
__init__(self, time: datetime.datetime, *, is_enabled: bool):
30
self.
_now
: datetime.datetime = time
31
self.
_is_enabled
= is_enabled
32
33
def
sleep
(self, delta: float) ->
None
:
34
"""Increase mock time value
35
36
:param delta: increase value in seconds
37
"""
38
if
not
self.
_is_enabled
:
39
raise
DisabledUsageError
(MOCK_TIME_DISABLED_MESSAGE)
40
self.
_now
+= datetime.timedelta(seconds=delta)
41
42
def
now
(self, tz: datetime.tzinfo |
None
=
None
) -> datetime.datetime:
43
""":returns: current value of mock time"""
44
now: datetime.datetime
45
if
self.
_is_enabled
:
46
now = self.
_now
47
else
:
48
now = utils.utcnow()
49
50
if
tz:
51
now = now.replace(tzinfo=UTC).astimezone(tz=tz)
52
53
return
now
54
55
def
set
(self, time: datetime.datetime):
56
"""Set mock time value"""
57
if
not
self.
_is_enabled
:
58
raise
DisabledUsageError
(MOCK_TIME_DISABLED_MESSAGE)
59
self.
_now
= utils.to_utc(time)
60
61
@property
62
def
is_enabled(self) -> bool:
63
return
self.
_is_enabled
64
65
66
def
pytest_addoption(parser):
67
parser.addini(
68
name=
'mocked-time-enabled'
,
69
type=
'bool'
,
70
default=
True
,
71
help=
'Set false to disable mocked time by default'
,
72
)
73
74
75
def
pytest_configure(config):
76
config.addinivalue_line(
77
'markers'
,
78
'now: specify current time mocked value'
,
79
)
80
81
82
def
pytest_register_object_hooks():
83
return
{
84
'$dateDiff'
: {
'$fixture'
:
'_date_diff_hook'
},
85
'$timeDelta'
: _time_delta_hook,
86
}
87
88
89
def
pytest_servicetest_modifyitem(session, item):
90
item.add_marker(pytest.mark.now(enabled=
False
))
91
92
93
@pytest.fixture
94
def
mocked_time
(
95
_mocked_time_enabled: bool,
96
now: datetime.datetime,
97
) -> MockedTime:
98
"""@returns @ref MockedTime
99
100
@ingroup userver_testsuite_fixtures
101
Part of the [yandex-taxi-testsuite](https://github.com/yandex/yandex-taxi-testsuite/blob/develop/testsuite/plugins/mocked_time.py#L94)
102
"""
103
return
MockedTime
(now, is_enabled=_mocked_time_enabled)
104
105
106
@pytest.fixture
107
def
now
(request) -> datetime.datetime:
108
marker = request.node.get_closest_marker(
'now'
)
109
if
not
marker
or
not
marker.args:
110
return
utils.utcnow()
111
stamp = marker.args[0]
112
if
isinstance(stamp, int):
113
return
utils.utcfromtimestamp(stamp)
114
return
utils.to_utc(dateutil.parser.parse(stamp))
115
116
117
@pytest.fixture
118
def
_mocked_time_enabled(request, pytestconfig) -> bool:
119
now_marker_exists =
False
120
for
marker
in
request.node.iter_markers(name=
'now'
):
121
if
'enabled'
in
marker.kwargs:
122
return
marker.kwargs[
'enabled'
]
123
now_marker_exists =
True
124
if
now_marker_exists:
125
return
True
126
return
pytestconfig.getini(
'mocked-time-enabled'
)
127
128
129
@pytest.fixture
130
def
_date_diff_hook(now: datetime.datetime):
131
def
wrapper(doc: dict):
132
seconds = float(doc[
'$dateDiff'
])
133
return
now + datetime.timedelta(seconds=seconds)
134
135
return
wrapper
136
137
138
def
_time_delta_hook(doc: dict):
139
delta = float(doc[
'$timeDelta'
])
140
return
datetime.timedelta(seconds=delta)
en
testsuite
plugins
mocked_time.py
Generated on
for userver by
Doxygen
1.17.0