Python跨模块捕获AssertionError时args缺失断言比对值问题
pytest跨模块断言丢失比对详情的原因与解决方案
产生原因
该现象由pytest的*断言重写(Assertion Rewriting)*机制默认规则导致:
- pytest为了给断言输出详细的上下文比对信息,会在导入模块时重写符合命名规则的测试文件内的
assert语句:通过修改AST抽象语法树,把原生断言逻辑替换为能自动拼接表达式实际值、期望值的版本,抛出异常时就会带上类似assert 2 == 3的详细内容。 - pytest默认仅重写文件名匹配
test_*.py/*_test.py规则的测试模块,以及conftest.py配置文件。你把断言逻辑放到普通工具文件helpers.py中时,这个文件里的assert不会被重写,抛出的是Python原生的AssertionError,仅会携带你手动定义的错误提示Incorrect number,不会自动追加断言比对详情。 - 同文件编写代码时能拿到完整信息,是因为
verify_number定义在测试文件内,函数内的断言也被pytest统一重写了。
解决方案
按优先级推荐两种可落地的方法:
- 手动注册需要重写断言的模块
在导入工具模块前,调用pytest提供的register_assert_rewrite方法,显式告诉pytest需要重写目标模块的断言,注意注册语句必须放在模块导入语句之前才会生效:
修改后再运行测试,跨模块抛出的断言异常就会携带完整的比对详情。import pytest # 注册要重写断言的模块,必须放在导入语句前 pytest.register_assert_rewrite("tests.helpers") from tests.helpers import verify_number def test_validate_number(): number = 2 try: verify_number(number) except AssertionError as exc: raise exc - 将工具断言逻辑放到pytest自动重写的文件中
如果你的断言工具函数会被多个测试文件复用,可以直接把相关逻辑写到测试目录下的conftest.py中,pytest会自动重写该文件内的所有断言,不需要额外手动注册。
内容的提问来源于stack exchange,提问作者Wine Torpedo
相关产品推荐
相关产品推荐

