Testing times can be a deadly game

When you want to test functions that deal with date, it could be harder than regular tests, especially if you deal with datetime.now, but workarounds exists !

La Volga depuis Nizhny Novgorod

TL;DR

To test processing and functions that use time functions in Python (i.e. datetime.now), you have two strategies: you set or you mock.

The Diff Side

Most of the time you can mock (use a fake object that “mimic the behavior of real objects”) datetime, but sometimes you can not mock because libraries you use in your code check types (ie: dateutil.relativedelta).

For instance if you want to test a function get_beginning_time_window that returns seconds since the beginning of a time window (defined by a string, ie “5 hours”). This compute is defined as: if you ask for a time window of 5 hours at 16h34 it must return (5*60 + 34) *60 (so seconds since 11h), so for “5 hours” this function could return 18000 to 21600. You could test it like that :

def test_get_beginning_time_window():
now = datetime.datetime.utcnow()
res = get_beginning_time_window('5 hours')
diff = (now-res).total_seconds()/60
self.assertEqual(18000 <= diff < 21600, True)

This is quite rough, but you can check that it looks like it works !

The Mock Side

On the mock side, it’s easier, and do not depend on current time, because you fix date and execute your function. For this function, that use datetime.datetime.now it’s like if you were at the date you fixed !

from unittest.mock import patchdef test_days_interval_from_now():
fixed_now = datetime.datetime(2020, 3, 30, 15)
with patch('datetime.datetime')as mock_dt:
mock_dt.now = lambda: fixed_now
days = days_interval_from_now(2020, 3, 3)
assert days = 27

Conclusion

We saw 2 ways to test a code that deals with datetimes, the best and easiest way is the mock one ! If you know other ways, let me know !

Thanks to Tiffany Souterre to read over :-)

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store