Freezegun:Python 时间冻结单元测试

Freezegun 冻结测试中的时间:@freeze_time 装饰器、上下文管理器、tick 推进时间、时区测试。调度任务、过期逻辑、时间条件的测试从此稳定可复现。

最佳实践
测试检测与质量验证插画

本文依据官方文档整理,未执行运行验证或性能基准。代码片段展示局部用法,业务函数、数据和环境需按项目补齐;版本与配置以所引文档为准。

直接回答:Freezegun 让测试里的 datetime.now() 返回你指定的时刻——@freeze_time("2026-01-15") 装饰器或上下文管理器冻结时间,tick() 推进,auto_tick_seconds 在读取受支持的时间 API 时按设定步长递增。测定时任务、过期判断、时间窗口逻辑的必备工具。

基本用法

from freezegun import freeze_time
import datetime

@freeze_time("2026-01-15 09:30:00")
def test_日报生成():
    assert get_report_date() == datetime.date(2026, 1, 15)

# 上下文管理器形态
def test_过期():
    with freeze_time("2026-01-01"):
        token = create_token(ttl_days=7)
    with freeze_time("2026-01-09"):
        assert token.is_expired()

时间推进

with freeze_time("2026-01-01 00:00") as frozen:
    step1()
    frozen.tick(delta=datetime.timedelta(hours=1))   # 推进 1 小时
    step2()
# 或在读取时间时自动递增
with freeze_time("2026-01-01", auto_tick_seconds=10):
    ...

时区测试

@freeze_time("2026-01-15 12:00", tz_offset=8)
def test_北京时间(): ...

tz_offset 是固定偏移,不是 Asia/Shanghai 等具备历史规则的 IANA 时区;示例中 UTC 的 now 为12点,本地无时区 now 为20点。跨夏令时业务应使用带 ZoneInfo 的 aware datetime 验证。

常见问题(FAQ)

Q:能冻结 time.sleep 吗?
A:不会加速真实 time.sleep。tick 推进模拟时钟,auto_tick_seconds 是每次取时自动递增,不会让阻塞的 sleep 自动结束。异步测试冻结 monotonic 可能卡住事件循环,可按文档用 real_asyncio=True。

Q:对第三方库生效吗?
A:对它支持并补丁到的 Python 时间调用有效,但忽略列表、默认参数绑定、某些持有引用的容器及 C/外部进程时间调用可能不受影响,不能保证所有第三方库均被冻结。

Q:和 pytest 怎么配?
A:直接装饰测试函数即可;也有 pytest-freezegun 插件提供 fixture 风格。

官方参考

资料核对日期:2026-09-29。

延伸阅读

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台