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

如何在非pytest环境中实现对象不等时的美观差异打印?

实现Pydantic对象的美观差异断言输出(非pytest环境)

在非pytest驱动的集成测试中,想要实现类似pytest的Pydantic对象差异美观打印,可以通过以下几种方式实现:

方法1:复用pytest的差异对比逻辑

pytest的断言差异输出依赖内部的_pytest.assertion.util模块,我们可以直接调用它来生成一致的差异格式:

from pydantic import BaseModel
from _pytest.assertion.util import assertrepr_compare

class Foo(BaseModel):
    id: str
    other_thing: str

def assert_pydantic_equal(a, b):
    if a != b:
        # 调用pytest的差异生成函数
        diff_lines = assertrepr_compare('==', a, b)
        raise AssertionError('\n'.join(diff_lines))

# 测试调用
oneFoo = Foo(id="red", other_thing="blue")
twoFoo = Foo(id="red", other_thing="green")
assert_pydantic_equal(oneFoo, twoFoo)

运行后会输出和pytest几乎一致的错误信息,包括高亮的差异标记。

方法2:手动实现Pydantic字段差异对比

如果不想依赖pytest的内部模块,可以自己遍历Pydantic对象的字段生成差异:

from pydantic import BaseModel

def generate_pydantic_diff(a: BaseModel, b: BaseModel) -> str:
    if type(a) != type(b):
        return f"类型不匹配: {type(a).__name__} vs {type(b).__name__}"
    
    diff_content = ["Full diff:"]
    model_name = type(a).__name__
    
    for field in a.model_fields:
        val_a = getattr(a, field)
        val_b = getattr(b, field)
        if val_a != val_b:
            # 生成类似pytest的差异行
            prefix_len = len(model_name) + 4 + len(field) + 2
            diff_content.append(f"- {model_name}(..., {field}={repr(val_b)}, ...)")
            diff_content.append(f"? {' ' * prefix_len} ^^^")
            diff_content.append(f"+ {model_name}(..., {field}={repr(val_a)}, ...)")
            diff_content.append(f"? {' ' * prefix_len} ^^^")
            diff_content.append("")
    
    return '\n'.join(diff_content)

def assert_pydantic_equal(a, b):
    if a != b:
        error_msg = f"assert {a} == {b}\n\n{generate_pydantic_diff(a, b)}"
        raise AssertionError(error_msg)

# 测试调用
oneFoo = Foo(id="red", other_thing="blue")
twoFoo = Foo(id="red", other_thing="green")
assert_pydantic_equal(oneFoo, twoFoo)

这种方式完全独立,适合没有安装pytest的环境。

方法3:使用第三方库DeepDiff

DeepDiff是专门用于对比复杂对象的库,能生成结构化的差异输出:

首先安装依赖:

pip install deepdiff

然后编写断言函数:

from pydantic import BaseModel
from deepdiff import DeepDiff

def assert_pydantic_equal(a: BaseModel, b: BaseModel):
    # 对比Pydantic对象的字典表示
    diff = DeepDiff(a.model_dump(), b.model_dump(), verbose_level=2)
    if diff:
        error_msg = f"assert {a} == {b}\n\nFull diff:\n{diff.pretty()}"
        raise AssertionError(error_msg)

# 测试调用
oneFoo = Foo(id="red", other_thing="blue")
twoFoo = Foo(id="red", other_thing="green")
assert_pydantic_equal(oneFoo, twoFoo)

它支持嵌套对象、列表、字典等多种结构的对比,输出格式清晰易读。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 00:52:43