如何让pytest自动为tests/目录下所有模块注册assert重写?
问题描述
项目结构
/app /app foo.py bar.py /tests __init__.py core.py test_foo.py test_bar.py
我在tests/core.py中编写了一些调用assert的函数,这些函数会被导入到test_foo.py和test_bar.py中使用。
默认执行pytest test_foo.py时,若assert是从core.py导入的函数内调用的,pytest不会格式化打印assert中用到的变量值。
目前已知的解决方法是在tests/__init__.py中添加以下代码:
import pytest pytest.register_assert_rewrite('tests.core')
但这种方式很繁琐,每次新增包含自定义断言的模块时,都得手动把模块名加到这个调用里。
有没有办法让pytest自动完成断言重写的注册,无需手动指定每个需要处理的模块?
解决方案
有两种简洁的方式可以实现自动注册:
方式一:直接注册整个tests包前缀
pytest支持传入包名前缀,会自动处理该包下的所有子模块,无需逐个指定。只需在项目根目录的conftest.py中添加以下代码:
import pytest def pytest_configure(config): pytest.register_assert_rewrite("tests")
方式二:自动扫描并注册所有模块(更灵活)
如果需要过滤部分模块,可以通过遍历tests目录的方式,自动注册符合条件的模块。同样在conftest.py中添加:
import sys from pathlib import Path import pytest def pytest_configure(config): # 获取tests目录的绝对路径 tests_dir = Path(__file__).parent / "tests" # 将项目根目录加入模块搜索路径 sys.path.insert(0, str(tests_dir.parent)) # 遍历tests下所有.py文件,排除缓存目录和__init__.py for py_file in tests_dir.rglob("*.py"): if "__pycache__" in str(py_file) or py_file.name == "__init__.py": continue # 转换为模块名格式(如tests/core.py → tests.core) relative_path = py_file.relative_to(tests_dir.parent) module_name = relative_path.with_suffix("").as_posix().replace("/", ".") try: pytest.register_assert_rewrite(module_name) except Exception: # 忽略导入失败的模块(如测试数据文件) pass
以上两种方式都能让pytest自动完成断言重写的注册,不用再手动维护模块列表。
内容的提问来源于stack exchange,提问作者Matthew Moisen
相关产品推荐
相关产品推荐

