How to mock/set system date in pytest?
在我的一些测试中,由于时间和时区问题,我遇到了Travis失败的问题,所以我想模拟系统时间进行测试。 我怎样才能做到这一点?
有两种方法可以实现这一目标:
根据Bruno的建议创建您将调用的函数而不是
1 2 3 4 5 6 7 8 | import os import datetime def mytoday(): if 'MYDATE' in os.environ: return datetime.datetime.strptime(os.getenv('MYDATE'), '%m-%d-%Y').date() else: return datetime.date.today() |
然后,在您的测试中,您只需monkeypatch环境变量:
1 2 3 4 5 | import datetime def test_patched_date(monkeypatch): monkeytest.setenv('MYDATE', '05-31-2014') assert datetime.date.today() == datetime.date(2014, 5, 31) |
Monkeypatch
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | import datetime import pytest FAKE_TIME = datetime.datetime(2020, 12, 25, 17, 05, 55) @pytest.fixture def patch_datetime_now(monkeypatch): class mydatetime: @classmethod def now(cls): return FAKE_TIME monkeypatch.setattr(datetime, 'datetime', mydatetime) def test_patch_datetime(patch_datetime_now): assert datetime.datetime.now() == FAKE_TIME |
AFAIK,你无法模拟内置方法。
我经常做的一种方法是将代码更改为不直接使用
1 2 3 4 | # mymodule.py def get_today(): return datetime.date.today() |
这使得在测试中只需
1 2 3 | def test_something(): with mock.patch('mymodule.get_today', return_value=datetime.date(2014, 6, 2)): ... |
您也可以使用freezegun模块。
@ Brian-Kruger的答案是最好的答案。 我已投票取消删除它。 同时...
使用freezegun(repo)。
来自README:
1 2 3 4 5 | from freezegun import freeze_time @freeze_time("2012-01-14") def test(): assert datetime.datetime.now() == datetime.datetime(2012, 1, 14) |