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

如何让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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 20:16:10