如何校验含数组的深层嵌套dict近似相等,是否可扩展pytest.approx?
深层嵌套混合结构近似相等校验实现方案
以下是问题场景用到的测试数据:
dict1 = { 'a': 1, 'b': [ {'c': [{'d': 32.069},{'e': 32.420}]} ] } dict2 = { 'a': 1, 'b': [ {'c': [{'d': 32.070},{'e': 32.421}]} ] }
方案1:自定义递归校验函数(兼容性最好、灵活度最高)
直接通过递归逻辑处理所有嵌套类型,自动适配dict、列表、数值的比对规则,可直接用于pytest测试用例中:
import pytest from typing import Any def assert_nested_approx(actual: Any, expected: Any, rel: float = None, abs: float = None) -> None: """ 递归校验嵌套结构的近似相等,支持dict、list、tuple、数值类型混合的嵌套结构 :param actual: 实际值 :param expected: 期望值 :param rel: 相对公差,透传给pytest.approx :param abs: 绝对公差,透传给pytest.approx """ # 数值类型用approx近似比对 if isinstance(expected, (int, float)) and isinstance(actual, (int, float)): assert actual == pytest.approx(expected, rel=rel, abs=abs) return # 字典类型先校验key一致,再递归比对value if isinstance(expected, dict) and isinstance(actual, dict): assert actual.keys() == expected.keys(), "字典key不匹配" for k in expected: assert_nested_approx(actual[k], expected[k], rel=rel, abs=abs) return # 列表/元组类型先校验长度一致,再递归比对元素 if isinstance(expected, (list, tuple)) and isinstance(actual, (list, tuple)): assert len(actual) == len(expected), "列表/元组长度不匹配" for a, b in zip(actual, expected): assert_nested_approx(a, b, rel=rel, abs=abs) return # 其他非数值类型直接做全等比对 assert actual == expected, f"非数值类型值不匹配:{actual} != {expected}"
调用示例:
# 绝对公差设为0.002即可通过示例场景的校验 assert_nested_approx(dict1, dict2, abs=0.002)
方案2:扩展pytest.approx支持嵌套结构
不需要修改pytest原生逻辑,通过预处理嵌套结构,将所有数值替换为approx包装对象即可实现适配:
import pytest from typing import Any def wrap_nested_approx(obj: Any, rel: float = None, abs: float = None) -> Any: """递归包装嵌套结构中的所有数值为pytest.approx对象""" if isinstance(obj, (int, float)): return pytest.approx(obj, rel=rel, abs=abs) if isinstance(obj, dict): return {k: wrap_nested_approx(v, rel=rel, abs=abs) for k, v in obj.items()} if isinstance(obj, list): return [wrap_nested_approx(item, rel=rel, abs=abs) for item in obj] if isinstance(obj, tuple): return tuple(wrap_nested_approx(item, rel=rel, abs=abs) for item in obj) return obj
调用示例:
# 包装后直接用==运算符比对即可 assert dict1 == wrap_nested_approx(dict2, abs=0.002)
注意事项
- 如果需要支持列表元素无序比对,可以在列表校验逻辑中先对可哈希元素排序后再比对
- 可根据业务需求扩展对其他自定义类型的校验逻辑
- 公差参数不传的话默认使用pytest.approx的默认值(相对公差1e-6,绝对公差1e-12)
内容的提问来源于stack exchange,提问作者amitava mozumder
相关产品推荐
相关产品推荐

