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

Python3.7+下pytest如何校验dict插入顺序并输出友好差异结果?

问题描述

从Python 3.7版本开始,dict已被官方明确保证遵循插入顺序。我目前在使用pytest编写单元测试,需要比对两个dict的同时校验元素的插入顺序是否一致。

我的应用不会在3.7以下版本的Python环境运行,无需考虑向后兼容性。

核心问题

是否可以在pytest中直接对比普通dict,既保留顺序校验能力,又能输出友好的差异提示?

已尝试的无效方案

  1. 直接用==对比dict:
a = {'x': 1, 'y': {'u': 3, 'v': 4}}
b = {'y': {'v': 4, 'u': 3}, 'x': 1}

assert a == b

这个断言会正常通过,但不符合预期:两个dict的值相等但插入顺序不一致。

  1. 递归转为OrderedDict后对比:
from collections import OrderedDict

def deep_ordered_dict(value):
    if isinstance(value, dict):
        value = OrderedDict(value)

        for k, v in value.items():
            value[k] = deep_ordered_dict(v)

    if isinstance(value, list):
        for k, v in enumerate(value):
            value[k] = deep_ordered_dict(v)

    return value

a = {'x': 1, 'y': {'u': 3, 'v': 4}}
b = {'y': {'v': 4, 'u': 3}, 'x': 1}

assert deep_ordered_dict(a) == deep_ordered_dict(b)

存在两个问题:

  • 代码冗余不美观
  • pytest输出的差异提示可读性很差
  1. 转为JSON字符串对比:
import json

a = {'x': 1, 'y': {'u': 3, 'v': 4}}
b = {'y': {'v': 4, 'u': 3}, 'x': 1}

assert json.dumps(a, indent=2) == json.dumps(b, indent=2)

存在问题:

  • pytest输出的差异提示可读性很差

解决方案

可以通过递归转换的方式实现需求,将dict按插入顺序转为嵌套的键值对列表后再做断言,pytest对列表类型的差异会输出直观的逐位对比提示,完全满足顺序校验和友好报错的要求。

示例代码如下:

def deep_to_ordered_pairs(obj):
    # 处理字典类型:转为按插入顺序排列的键值对列表
    if isinstance(obj, dict):
        return [(k, deep_to_ordered_pairs(v)) for k, v in obj.items()]
    # 处理列表类型:递归处理每个元素
    if isinstance(obj, list):
        return [deep_to_ordered_pairs(item) for item in obj]
    # 其他类型直接返回原值
    return obj

# 测试用例
a = {'x': 1, 'y': {'u': 3, 'v': 4}}
b = {'y': {'v': 4, 'u': 3}, 'x': 1}

assert deep_to_ordered_pairs(a) == deep_to_ordered_pairs(b)

该方案的优势:

  • 无额外依赖,代码简洁易维护
  • 完全遵循Python3.7+原生dict的插入顺序规则,嵌套结构也可以正常校验
  • pytest输出的差异提示和原生列表对比完全一致,会明确标出哪一层的第几个键值对不匹配,可读性极强

如果需要频繁使用该校验逻辑,可以把转换函数封装到公共测试工具模块中,调用成本极低。


内容的提问来源于stack exchange,提问作者j123b567

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 17:24:02