pytest的AST 断言重写

"AST 断言重写"

你平时写 assert result == expected,在 Pytest 底层,这行代码在运行前就被语法树(AST)重写了。

Pytest 把它变成了一段极其复杂的代码,不仅判断结果对不对,还会把 result 和 expected 的每一个属性、每一个变量的值都打印出来。这就是为什么 Pytest 报错时,能给你提供那么丰富、那么详细的上下文信息。

一个极其重要的"避坑"指南

既然你学到了这里,我必须告诉你一个 AST 重写机制的致命弱点:

如果你在 assert 后面加了自定义的提示信息,AST 重写就会立刻失效!

python 复制代码
# ❌ 错误写法:加了逗号后面的提示信息,Pytest 的丰富报错就没了!
assert a == b, "a 和 b 不相等"

# ✅ 正确写法:让 Pytest 尽情发挥 AST 重写的能力
assert a == b 

为什么? 因为 Pytest 的 AST 重写机制在解析语法树时,如果发现 assert 节点带了自定义的 Message 参数,为了尊重开发者的原始意图,它会放弃重写,退化为原生 Python 的 raise AssertionError("a 和 b 不相等")。

真正想问的底层逻辑是:Pytest 的底层源码,究竟是如何"看懂"并识别出 assert a == b, "提示信息" 这种带逗号写法的?

这就要回到我们上一轮聊到的核心概念:AST(抽象语法树)。

在 Python 的 AST 语法树眼里,assert 语句并不是简单的文本,而是一个结构化的"节点(Node)"。这个节点有两个非常关键的属性(插槽):

test:存放断言的条件(比如 a == b)。

msg:存放自定义的提示信息(比如 "a 和 b 不相等")。

当你在代码里写下这两种不同的写法时,Python 编译器生成的 AST 节点是完全不同的:

写法一:不带提示信息

python 复制代码
assert a == b

生成的 AST 节点:
test = a == b
msg = None (空的)

写法二:带了提示信息(有逗号)

python 复制代码
assert a == b, "a 和 b 不相等"

生成的 AST 节点:
test = a == b
msg = "a 和 b 不相等" (有具体的字符串值)

Pytest 源码是如何"看懂"的?

Pytest 在重写代码时,会在源码里写一个极其明确的 if...else... 判断逻辑(你可以去 Pytest 源码 src/_pytest/assertion/rewrite.py 的 visit_Assert 方法里亲眼看到它)。

它的底层伪代码逻辑大概是这样的:

python 复制代码
def visit_Assert(self, node):
    # Pytest 在这里"看" AST 节点的 msg 属性
    if node.msg is not None:
        # 发现 msg 不是空的!说明用户自己写了自定义提示信息。
        # 策略:放弃重写,直接保留原样,退化为原生 Python 的 assert 行为。
        return node 
    else:
        # 发现 msg 是空的!说明用户只写了 assert a == b。
        # 策略:启动 AST 魔法重写,把这段代码变成包含丰富调试信息的复杂代码!
        return self.rewrite_assert(node)

总结

所以,计算机(Pytest)并不是像人类一样去"阅读"你的注释或代码习惯。它是通过解析 AST 语法树的结构,极其精确地判断 msg 这个属性到底有没有值。

如果 msg 有值,它就认为:"哦,用户有自己的报错需求,我不插手。"

如果 msg 没值,它就认为:"太好了,用户需要我的高级调试功能,我来重写它!"

相关推荐
Tinyfacture1 天前
接口自动化之添加商品(pytest)
python·测试工具·自动化·pytest
ji_shuke3 天前
从零深入:基于 Playwright + Pytest + Allure 的企业级 Web 端到端自动化测试框架实战
前端·自动化测试·docker·jenkins·pytest·allure·playwright
祉猷并茂,雯华若锦4 天前
Selenium+Pytest自动化测试框架实战
selenium·测试工具·pytest
祉猷并茂,雯华若锦6 天前
Pytest+Selenium自动化测试:失败自动截图集成Allure报告
selenium·测试工具·pytest
我的xiaodoujiao9 天前
API 接口自动化测试详细图文教程学习系列32--Allure测试报告2
python·学习·测试工具·pytest
一孤程12 天前
Pytest+Selenium搭建自动化框架-保姆级实战教程
selenium·自动化·pytest
名字还没想好☜16 天前
用 pytest fixture 组织可维护的测试:告别一堆重复的 setUp
数据库·python·oracle·pytest·测试
自动化和Linux18 天前
【pytest在pycharm中运行与CMD命令运行区别一】
python·pycharm·pytest
博观而约取厚积而薄发19 天前
Pytest 从入门到精通,一篇就够(超详细实战教程)
python·测试工具·单元测试·自动化·pytest