To test time-dependant programs, such as timelapse camera, we can fudge the system time (sleep,. now()) in Python. Some options are:
- https://github.com/spulec/freezegun/ This is easy to use, but doesn’t manage sleep(). Use monkeypatch to override sleep().
- Another is unittest.mock (good intro) which is harder but more flexible. Probably could do everything in this, but it’s harder IMHO.
An example using freezegun and monkeypatch
# chilly_bin_test.py
#
from freezegun import freeze_time
import time
import another_module
def test_capture(monkeypatch):
# fake time with freezegun
with freeze_time(parse("2000-01-01 00:00:00")) as frozen_datetime:
def sleepless(s):
""" instead of really sleeping, just move frozen time forward """
td = timedelta(seconds=s)
frozen_datetime.tick(td)
c1 = Camera()
c1.config("./camera_app/tests/camera-test-config-1.toml")
# replace real camera will a dummy using Mock. Could also use monkeypatch (?)
c1._camera = unittest.mock.MagicMock(capture=True)
# fake sleeping using monkeypatch
monkeypatch.setattr(time, 'sleep', sleepless)
# Now time.sleep() runs sleepless():
time.sleep(10) # locally ...
c1.run(3) # and works in another module
# another_module.py
#
import time # careful will naming of time, datetime, etc because
# there is also a datetime.datetime.sleep
class Camera():
def run(n):
time.sleep(10) # won't really sleep! use full name
An example of time changing using mock:
import unittest.mock
from datetime import datetime # for local use
# normally in another module
def thing_to_test():
from datetime import datetime # load so can be patched !!!
print("thing_to_test: {}".format(datetime.now()))
print("thing_to_test: {}".format(datetime.now()))
ts = [datetime(2000, 1, 1, 1, 1, 1), datetime(2000, 1, 2, 1, 1, 1)]
@unittest.mock.patch('datetime.datetime')
def test2(self):
self.now.side_effect = ts
thing_to_test()
test2()