conftest.py找不到的根本原因是pytest仅在推断出的rootdir及其子目录中搜索,而非当前工作目录或Git根目录;rootdir由命令行路径向上查找pyproject.toml、pytest.ini等配置文件确定,若未找到则以最外层测试路径为rootdir。

conftest.py 找不到,根本不是文件丢了,而是 pytest 根本没在你认为的位置搜它——它只认自己推出来的 rootdir,不认你当前终端在哪、也不认 Git 根目录。
pytest 怎么确定 rootdir?它根本不看你在哪敲的命令
pytest 从你传入的路径(比如 tests/unit/ 或 tests/test_api.py)开始,**向上逐级找配置文件**,一旦遇到以下任一文件就停,该目录就是 rootdir:
-
pyproject.toml(且含[tool.pytest.ini_options]) pytest.initox.inisetup.py
如果全都没找到,它就用你传入路径的最外层目录当 rootdir。所有 conftest.py 必须落在这个 rootdir 及其子目录里,才可能被加载。
验证方法:运行 pytest --debug,看输出里 rootdir: 后面的路径是不是你放 conftest.py 的父目录。如果不是,它就彻底无视那个文件。
立即学习“Python免费学习笔记(深入)”;
conftest.py 放对了位置,还是不生效?检查这三处硬伤
- 文件名必须严格是
conftest.py:大小写敏感(conftest.PY、conf_test.py、conftest.pyc全都不行) - 所在目录要是 Python 包:必须有
__init__.py(尤其在 pytest ≤ 7.3 或跨包引用 fixture 时,缺它会导致 fixture 不注册) - 多个同名 fixture 被静默覆盖:比如
tests/conftest.py和tests/integration/conftest.py都定义了@pytest.fixture def db(),后者会直接屏蔽前者,且不报错
为什么加了 pythonpath=. 还是报 fixture not found?
pythonpath=. 只影响 Python 模块导入(比如 import mylib),跟 conftest.py 的发现逻辑完全无关。这是两套独立机制:
-
conftest.py加载:纯靠rootdir+ 目录树扫描 - 模块导入:靠
PYTHONPATH/sys.path
所以你在 conftest.py 里写 from mypkg.utils import helper 报 ModuleNotFoundError,那是导入失败;但测试里调用 helper fixture 报 fixture not found,说明 conftest.py 压根没被加载进来——别往 pythonpath 上猜。
pytest ≥ 7.4 启动时 rootdir 卡在子目录?补个空配置最稳
如果项目根目录下没有 pyproject.toml 或 pytest.ini,pytest ≥ 7.4 默认不会往上推到你认为的“项目根”,而是卡在你传入的测试子目录(比如 tests/)作为 rootdir。结果就是:你把 conftest.py 放在项目根,它看不见。
最快解法:在项目最外层目录建一个空的 pytest.ini 文件(内容可以就一行 [tool:pytest])。这样它就能稳定把项目根识别为 rootdir,后续所有子目录下的测试都能正确继承上层 conftest.py。
真正容易被忽略的是:rootdir 是 pytest 自己推出来的,不是你“觉得应该是什么”。哪怕 conftest.py 文件存在、拼写正确、也有 init.py,只要它不在 rootdir 下,就等于不存在——连报错都不会有,只会静默跳过。


















