跳转到主要内容

让你的Python测试穿越时光

项目描述

https://img.shields.io/pypi/v/freezegun.svg https://github.com/spulec/freezegun/workflows/CI/badge.svg https://coveralls.io/repos/spulec/freezegun/badge.svg?branch=master

FreezeGun是一个库,允许您的Python测试通过模拟datetime模块穿越时光。

用法

一旦调用装饰器或上下文管理器,对datetime.datetime.now()、datetime.datetime.utcnow()、datetime.date.today()、time.time()、time.localtime()、time.gmtime()和time.strftime()的所有调用都将返回已冻结的时间。time.monotonic()和time.perf_counter()也将被冻结,但通常它不对它们的绝对值做出保证,只对它们随时间的变化做出保证。

装饰器

from freezegun import freeze_time
import datetime
import unittest

# Freeze time for a pytest style test:

@freeze_time("2012-01-14")
def test():
    assert datetime.datetime.now() == datetime.datetime(2012, 1, 14)

# Or a unittest TestCase - freezes for every test, and set up and tear down code

@freeze_time("1955-11-12")
class MyTests(unittest.TestCase):
    def test_the_class(self):
        assert datetime.datetime.now() == datetime.datetime(1955, 11, 12)

# Or any other class - freezes around each callable (may not work in every case)

@freeze_time("2012-01-14")
class Tester(object):
    def test_the_class(self):
        assert datetime.datetime.now() == datetime.datetime(2012, 1, 14)

# Or method decorator, might also pass frozen time object as kwarg

class TestUnitTestMethodDecorator(unittest.TestCase):
    @freeze_time('2013-04-09')
    def test_method_decorator_works_on_unittest(self):
        self.assertEqual(datetime.date(2013, 4, 9), datetime.date.today())

    @freeze_time('2013-04-09', as_kwarg='frozen_time')
    def test_method_decorator_works_on_unittest(self, frozen_time):
        self.assertEqual(datetime.date(2013, 4, 9), datetime.date.today())
        self.assertEqual(datetime.date(2013, 4, 9), frozen_time.time_to_freeze.today())

    @freeze_time('2013-04-09', as_kwarg='hello')
    def test_method_decorator_works_on_unittest(self, **kwargs):
        self.assertEqual(datetime.date(2013, 4, 9), datetime.date.today())
        self.assertEqual(datetime.date(2013, 4, 9), kwargs.get('hello').time_to_freeze.today())

上下文管理器

from freezegun import freeze_time

def test():
    assert datetime.datetime.now() != datetime.datetime(2012, 1, 14)
    with freeze_time("2012-01-14"):
        assert datetime.datetime.now() == datetime.datetime(2012, 1, 14)
    assert datetime.datetime.now() != datetime.datetime(2012, 1, 14)

原始使用

from freezegun import freeze_time

freezer = freeze_time("2012-01-14 12:00:01")
freezer.start()
assert datetime.datetime.now() == datetime.datetime(2012, 1, 14, 12, 0, 1)
freezer.stop()

时区

from freezegun import freeze_time

@freeze_time("2012-01-14 03:21:34", tz_offset=-4)
def test():
    assert datetime.datetime.utcnow() == datetime.datetime(2012, 1, 14, 3, 21, 34)
    assert datetime.datetime.now() == datetime.datetime(2012, 1, 13, 23, 21, 34)

    # datetime.date.today() uses local time
    assert datetime.date.today() == datetime.date(2012, 1, 13)

@freeze_time("2012-01-14 03:21:34", tz_offset=-datetime.timedelta(hours=3, minutes=30))
def test_timedelta_offset():
    assert datetime.datetime.now() == datetime.datetime(2012, 1, 13, 23, 51, 34)

良好的输入

FreezeGun在幕后使用dateutil,因此您可以使用看起来不错的datetimes。

@freeze_time("Jan 14th, 2012")
def test_nice_datetime():
    assert datetime.datetime.now() == datetime.datetime(2012, 1, 14)

函数和生成器对象

FreezeGun能够处理函数和生成器对象。

def test_lambda():
    with freeze_time(lambda: datetime.datetime(2012, 1, 14)):
        assert datetime.datetime.now() == datetime.datetime(2012, 1, 14)

def test_generator():
    datetimes = (datetime.datetime(year, 1, 1) for year in range(2010, 2012))

    with freeze_time(datetimes):
        assert datetime.datetime.now() == datetime.datetime(2010, 1, 1)

    with freeze_time(datetimes):
        assert datetime.datetime.now() == datetime.datetime(2011, 1, 1)

    # The next call to freeze_time(datetimes) would raise a StopIteration exception.

tick 参数

FreezeGun 有一个额外的 tick 参数,可以将时间重置到指定值,但时间会继续流逝。这是对默认参数的替代,默认参数会使时间停止。

@freeze_time("Jan 14th, 2020", tick=True)
def test_nice_datetime():
    assert datetime.datetime.now() > datetime.datetime(2020, 1, 14)

auto_tick_seconds 参数

FreezeGun 有一个额外的 auto_tick_seconds 参数,每次从起始值自动递增指定数量的值。这是对默认参数的替代,默认参数会使时间停止。注意,给定 auto_tick_seconds 后,tick 参数将被忽略。

@freeze_time("Jan 14th, 2020", auto_tick_seconds=15)
def test_nice_datetime():
    first_time = datetime.datetime.now()
    auto_incremented_time = datetime.datetime.now()
    assert first_time + datetime.timedelta(seconds=15) == auto_incremented_time

手动计时

FreezeGun 允许手动向前推进时间。

def test_manual_tick():
    initial_datetime = datetime.datetime(year=1, month=7, day=12,
                                        hour=15, minute=6, second=3)
    with freeze_time(initial_datetime) as frozen_datetime:
        assert frozen_datetime() == initial_datetime

        frozen_datetime.tick()
        initial_datetime += datetime.timedelta(seconds=1)
        assert frozen_datetime() == initial_datetime

        frozen_datetime.tick(delta=datetime.timedelta(seconds=10))
        initial_datetime += datetime.timedelta(seconds=10)
        assert frozen_datetime() == initial_datetime
def test_monotonic_manual_tick():
    initial_datetime = datetime.datetime(year=1, month=7, day=12,
                                        hour=15, minute=6, second=3)
    with freeze_time(initial_datetime) as frozen_datetime:
        monotonic_t0 = time.monotonic()
        frozen_datetime.tick(1.0)
        monotonic_t1 = time.monotonic()
        assert monotonic_t1 == monotonic_t0 + 1.0

将时间移动到指定日期时间

FreezeGun 允许将时间移动到特定日期。

def test_move_to():
    initial_datetime = datetime.datetime(year=1, month=7, day=12,
                                        hour=15, minute=6, second=3)

    other_datetime = datetime.datetime(year=2, month=8, day=13,
                                        hour=14, minute=5, second=0)
    with freeze_time(initial_datetime) as frozen_datetime:
        assert frozen_datetime() == initial_datetime

        frozen_datetime.move_to(other_datetime)
        assert frozen_datetime() == other_datetime

        frozen_datetime.move_to(initial_datetime)
        assert frozen_datetime() == initial_datetime


@freeze_time("2012-01-14", as_arg=True)
def test(frozen_time):
    assert datetime.datetime.now() == datetime.datetime(2012, 1, 14)
    frozen_time.move_to("2014-02-12")
    assert datetime.datetime.now() == datetime.datetime(2014, 2, 12)

move_to 参数可以是任何有效的 freeze_time 日期(字符串、日期、datetime)。

默认参数

请注意,FreezeGun 不会修改默认参数。以下代码将打印当前日期。请参阅此处了解原因。

from freezegun import freeze_time
import datetime as dt

def test(default=dt.date.today()):
    print(default)

with freeze_time('2000-1-1'):
    test()

安装

要安装 FreezeGun,只需

$ pip install freezegun

在 Debian 系统上

$ sudo apt-get install python-freezegun

忽略包

有时需要忽略特定包(例如库)的 FreezeGun 行为。可以通过单个调用忽略它们

from freezegun import freeze_time

with freeze_time('2020-10-06', ignore=['threading']):
    # ...

默认情况下,FreezeGun 忽略以下包

[
    'nose.plugins',
    'six.moves',
    'django.utils.six.moves',
    'google.gax',
    'threading',
    'Queue',
    'selenium',
    '_pytest.terminal.',
    '_pytest.runner.',
    'gi',
]

可以设置自己的默认忽略列表

import freezegun

freezegun.configure(default_ignore_list=['threading', 'tensorflow'])

请注意,这将覆盖默认忽略列表。如果想要扩展现有默认值,请使用

import freezegun

freezegun.configure(extend_ignore_list=['tensorflow'])

项目详情


发布历史 发布通知 | RSS 源

下载文件

下载您平台的文件。如果您不确定选择哪个,请了解有关 安装包 的更多信息。

源代码发行版

freezegun-1.5.1.tar.gz (33.7 kB 查看哈希值)

上传时间 源代码

构建发行版

freezegun-1.5.1-py3-none-any.whl (17.6 kB 查看哈希值)

上传时间 Python 3

由以下支持