Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(449)

Side by Side Diff: infra_libs/time_functions/testing.py

Issue 2213143002: Add infra_libs as a bootstrap dependency. (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@master
Patch Set: Removed the ugly import hack Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 # Copyright 2015 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4
5
6 """Provides functions to mock current time in tests."""
7
8 import datetime
9 import functools
10 import mock
11 import pytz
12 import tzlocal
13
14
15 def mock_datetime_utc(*dec_args, **dec_kwargs):
16 """Overrides built-in datetime and date classes to always return a given time.
17
18 Args:
19 Same arguments as datetime.datetime accepts to mock UTC time.
20
21 Example usage:
22 @mock_datetime_utc(2015, 10, 11, 20, 0, 0)
23 def my_test(self):
24 hour_ago_utc = datetime.datetime.utcnow() - datetime.timedelta(hours=1)
25 self.assertEqual(hour_ago_utc, datetime.datetime(2015, 10, 11, 19, 0, 0))
26
27 Note that if you are using now() and today() methods, you should also use
28 mock_timezone decorator to have consistent test results across timezones:
29
30 @mock_timezone('US/Pacific')
31 @mock_datetime_utc(2015, 10, 11, 20, 0, 0)
32 def my_test(self):
33 local_dt = datetime.datetime.now()
34 self.assertEqual(local_dt, datetime.datetime(2015, 10, 11, 12, 0, 0))
35 """
36 # We record original values currently stored in the datetime.datetime and
37 # datetime.date here. Note that they are no necessarily vanilla Python types
38 # and can already be mock classes - this can happen if nested mocking is used.
39 original_datetime = datetime.datetime
40 original_date = datetime.date
41
42 # Our metaclass must be derived from the parent class metaclass, but if the
43 # parent class doesn't have one, we use 'type' type.
44 class MockDateTimeMeta(original_datetime.__dict__.get('__metaclass__', type)):
45 @classmethod
46 def __instancecheck__(cls, instance):
47 return isinstance(instance, original_datetime)
48
49 class _MockDateTime(original_datetime):
50 __metaclass__ = MockDateTimeMeta
51 mock_utcnow = original_datetime(*dec_args, **dec_kwargs)
52
53 @classmethod
54 def utcnow(cls):
55 return cls.mock_utcnow
56
57 @classmethod
58 def now(cls, tz=None):
59 if not tz:
60 tz = tzlocal.get_localzone()
61 tzaware_utcnow = pytz.utc.localize(cls.mock_utcnow)
62 return tz.normalize(tzaware_utcnow.astimezone(tz)).replace(tzinfo=None)
63
64 @classmethod
65 def today(cls):
66 return cls.now().date()
67
68 @classmethod
69 def fromtimestamp(cls, timestamp, tz=None):
70 if not tz:
71 # TODO(sergiyb): This may fail for some unclear reason because pytz
72 # doesn't find normal timezones such as 'Europe/Berlin'. This seems to
73 # happen only in appengine/chromium_try_flakes tests, and not in tests
74 # for this module itself.
75 tz = tzlocal.get_localzone()
76 tzaware_dt = pytz.utc.localize(cls.utcfromtimestamp(timestamp))
77 return tz.normalize(tzaware_dt.astimezone(tz)).replace(tzinfo=None)
78
79 # Our metaclass must be derived from the parent class metaclass, but if the
80 # parent class doesn't have one, we use 'type' type.
81 class MockDateMeta(original_date.__dict__.get('__metaclass__', type)):
82 @classmethod
83 def __instancecheck__(cls, instance):
84 return isinstance(instance, original_date)
85
86 class _MockDate(original_date):
87 __metaclass__ = MockDateMeta
88
89 @classmethod
90 def today(cls):
91 return _MockDateTime.today()
92
93 @classmethod
94 def fromtimestamp(cls, timestamp, tz=None):
95 return _MockDateTime.fromtimestamp(timestamp, tz).date()
96
97 def decorator(func):
98 @functools.wraps(func)
99 def wrapper(*args, **kwargs):
100 with mock.patch('datetime.datetime', _MockDateTime):
101 with mock.patch('datetime.date', _MockDate):
102 return func(*args, **kwargs)
103 return wrapper
104 return decorator
105
106
107 def mock_timezone(tzname):
108 """Mocks tzlocal.get_localzone method to always return a given timezone.
109
110 This should be used in combination with mock_datetime_utc in order to achieve
111 consistent test results accross timezones if datetime.now, datetime.today or
112 date.today functions are used.
113
114 Args:
115 tzname: Name of the timezone to be used (as passed to pytz.timezone).
116 """
117 # TODO(sergiyb): Also mock other common libraries, e.g. time, pytz.reference.
118 def decorator(func):
119 @functools.wraps(func)
120 def wrapper(*args, **kwargs):
121 with mock.patch('tzlocal.get_localzone', lambda: pytz.timezone(tzname)):
122 return func(*args, **kwargs)
123 return wrapper
124 return decorator
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698