DeepDiff是当前最可控、信息最透明的递归比较工具,支持嵌套结构对比、差异类型分类、忽略字段及自定义比较,而pytest-deep-compare因多年未维护、兼容性差且调试不透明,不建议使用。

直接用 == 断言嵌套字典或含动态字段的对象,十有八九会失败——不是逻辑错,是结构太“毛糙”。DeepDiff 不是万能胶,但它是目前最可控、信息最透明的递归比较工具;pytest-deep-compare 并非主流方案,且已多年未维护,不建议引入。
为什么不用 pytest-deep-compare
这个包在 PyPI 上最后一次更新是 2019 年,不兼容 Python 3.10+ 的部分语法,且与 pytest 7/8 的断言重写机制存在冲突。实际使用中常出现:
AttributeError: 'DeepComparison' object has no attribute '_repr'- 报错时只显示
False,不输出任何差异路径 - 无法忽略浮点误差、时间戳、UUID 等常见噪声字段
它试图封装比较逻辑,但把控制权交给了黑盒,调试成本反而更高。
用 DeepDiff 做可读、可控、可复用的断言
核心是别把它当“断言函数”用,而要当“差异报告器”用。返回值不是布尔值,而是字典,必须显式检查键是否存在。
立即学习“Python免费学习笔记(深入)”;
- 断言通过的条件是
not DeepDiff(a, b, ...),不是DeepDiff(a, b, ...) == {}(后者在空 diff 时会报TypeError) - 必加
ignore_order=True:否则列表顺序不同就判为失败,哪怕内容完全一致 - 对含浮点数的字段,用
significant_digits=2比abs=0.01更稳妥(尤其当数值跨数量级时) - 忽略字段用
exclude_paths=["root['updated_at']", "root['id']"],路径必须带root[...]前缀
示例:
from deepdiff import DeepDiff
<p>def assert_api_response(actual, expected):
diff = DeepDiff(
actual, expected,
ignore_order=True,
significant_digits=2,
exclude_paths=["root['request_id']", "root['timestamp']"]
)
if diff:
raise AssertionError(f"API response mismatch:\n{diff}")</p><h1>在 test 中调用</h1><p>assert_api_response(resp.json(), expected_dict)
容易被忽略的三个细节
很多人跑通一次就以为万事大吉,结果在 CI 或换环境后突然失败:
-
verbose_level=0会清空所有路径信息,只剩{}或{"values_changed": {...}},但没具体 key 路径,根本没法定位——调试时务必设为2 - 如果
actual是requests.Response对象,别直接传r,得先r.json();传原始响应对象会触发UnhashableType错误 - DeepDiff 默认不比较函数、方法、模块等类型,但若字典里混了
lambda或自定义类实例,会静默跳过——得加ignore_type_in_groups=[(list, tuple)]显式声明忽略规则


















