You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何校验含数组的深层嵌套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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 11:15:03