pytest.approx是解决浮点数断言失败的必备工具,因ieee 754精度问题,0.1+0.2≠0.3字面值;它通过相对/绝对误差容差(默认1e-6)实现语义相等判断,支持数字、数组、嵌套字典等结构。

pytest.approx 是解决浮点数断言失败最直接、最可靠的方式——它不是“可选方案”,而是**必须用**的工具,只要涉及浮点计算,硬写 == 就大概率翻车。
为什么 0.1 + 0.2 == 0.3 在测试里会失败
这不是 pytest 的 bug,是 IEEE 754 浮点表示的固有特性:0.1 + 0.2 实际算出来是 0.30000000000000004,而 0.3 存储为 0.29999999999999999(或类似),二者字面值不等。assert 做的是精确二进制比对,不会做语义近似。
pytest.approx 怎么用才不踩坑
- 基本写法:
assert actual == pytest.approx(expected)—— 注意是==左边放实际值,右边放pytest.approx()包裹的期望值 - 绝对容差更安全:浮点字段如价格、温度、评分,优先用
abs=0.01,比如assert resp["price"] == pytest.approx(19.99, abs=0.01) - 相对容差慎用:
rel=1e-3对1000.0允许 ±1.0,但对0.001只允许 ±1e-6,容易漏过小数值偏差 - 别传字符串进去:
pytest.approx("3.14")会静默失败,只接受数字、数字序列、字典或 numpy 数组 - 嵌套字典里有浮点?
pytest.approx支持直接比较整个字典:assert data == pytest.approx({"score": 95.5, "rate": 0.83})
什么情况不能只靠 pytest.approx
它能处理精度问题,但解决不了其他常见干扰:
- JSON 解析后带多余空格的字符串字段:
"updated_at": "2026-04-12 10:30:45 "→ 得先.strip()再断言 - 时间戳字段含毫秒但预期只关心秒级:
pytest.approx不管时间格式,得提前int(timestamp)或用datetime截断 - 字段类型混用:API 返回
"count": 5.0(float),你预期"count": 5(int)→pytest.approx(5)会通过,但语义上可能不该允许 float/int 混用,这时应加类型检查:assert isinstance(resp["count"], int) - NaN 值默认不相等:如果 API 显式返回
NaN,需显式开启nan_ok=True:assert val == pytest.approx(float("nan"), nan_ok=True)
替代方案对比:什么时候该换别的
pytest.approx 覆盖 90% 场景,但以下情况建议切换:
- 金融计算要求严格精度:改用
decimal.Decimal,避免浮点路径本身 - 要复用已有逻辑(如和生产代码共用判断):用
math.isclose(actual, expected, abs_tol=0.01),但注意它返回布尔值,得包在assert里 - 需要自定义比较行为(如忽略某些 key、递归跳过 None):写个封装函数,别把
approx当万能胶水硬贴
abs= 前,得清楚这个数字代表什么物理/业务含义。Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











