Pytest从项目根目录执行测试找不到模块,如何正确配置测试收集规则
背景
我需要测试一份与他人协作的项目,目前已将问题简化为如下最小可复现示例。
项目结构如下:
. ├── Problem1 │ ├── p1.py │ └── tests │ └── test_p1.py └── Problem2 ├── p2.py └── tests └── test_p2.py
p1.py 内容
def add_two_numbers(x1, x2): return x1+x2
test_p1.py 内容
import pytest from p1 import add_two_numbers def test_add_two_numbers(): assert add_two_numbers(1,2)==3
p2.py 内容
def subtract_two_numbers(x1,x2): return x1-x2
test_p2.py 内容
import pytest from p2 import subtract_two_numbers def test_subtract_two_numbers(): assert subtract_two_numbers(5,2)==3
问题描述
在 Problem1 或 Problem2 目录内执行 pytest,可以正常收集并运行对应测试文件中的用例。
但从项目根目录直接执行 pytest 时会触发导入错误,pytest 运行失败,报错信息如下:
=============================================================================== test session starts =============================================================================== platform linux -- Python 3.8.6, pytest-6.2.3, py-1.10.0, pluggy-0.13.1 rootdir: /home/awa5114/code/awa5114/example plugins: dash-1.20.0, anyio-2.2.0 collected 0 items / 2 errors ===================================================================================== ERRORS ====================================================================================== ___________________________________________________________________ ERROR collecting Problem1/tests/test_p1.py ____________________________________________________________________ ImportError while importing test module '/home/awa5114/code/awa5114/example/Problem1/tests/test_p1.py'. Hint: make sure your test modules/packages have valid Python names. Traceback: ../../../.pyenv/versions/3.8.6/lib/python3.8/importlib/__init__.py:127: in import_module return _bootstrap._gcd_import(name[level:], package, level) Problem1/tests/test_p1.py:2: in <module> from p1 import add_two_numbers E ModuleNotFoundError: No module named 'p1' ___________________________________________________________________ ERROR collecting Problem2/tests/test_p2.py ____________________________________________________________________ ImportError while importing test module '/home/awa5114/code/awa5114/example/Problem2/tests/test_p2.py'. Hint: make sure your test modules/packages have valid Python names. Traceback: ../../../.pyenv/versions/3.8.6/lib/python3.8/importlib/__init__.py:127: in import_module return _bootstrap._gcd_import(name[level:], package, level) Problem2/tests/test_p2.py:2: in <module> from p2 import subtract_two_numbers E ModuleNotFoundError: No module named 'p2' ============================================================================= short test summary info ============================================================================= ERROR Problem1/tests/test_p1.py ERROR Problem2/tests/test_p2.py !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 2 errors during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ================================================================================ 2 errors in 0.07s ================================================================================
请问如何调整配置,才能在项目根目录执行 pytest 时正常识别对应的业务模块,完成测试用例的收集与运行?
解决方案
这个报错本质是Python模块搜索路径匹配问题:在子目录执行pytest时,当前工作目录会被自动加入模块搜索路径,所以测试文件可以直接找到同层级的p1.py、p2.py;在根目录执行时,Problem1、Problem2目录不在默认搜索路径内,就会找不到对应模块。可以按场景选择以下方案:
方案1:添加pytest配置文件(推荐,无需修改业务代码)
在项目根目录新建pytest.ini文件,写入以下内容:
[pytest] pythonpath = Problem1 Problem2
配置完成后直接在根目录执行pytest即可正常运行,同时不会影响原来在子目录执行pytest的逻辑,适配多人协作场景。
方案2:调整为标准Python包结构(适合长期维护的项目)
- 在
Problem1、Problem1/tests、Problem2、Problem2/tests目录下分别新增空的__init__.py文件,将目录标记为Python包 - 修改测试文件的导入语句:
- test_p1.py改为
from Problem1.p1 import add_two_numbers - test_p2.py改为
from Problem2.p2 import subtract_two_numbers
调整后符合Python官方的包管理规范,后续新增模块也不需要频繁修改pytest配置。
- test_p1.py改为
方案3:临时指定搜索路径(适合临时调试)
执行pytest前临时指定PYTHONPATH环境变量:
- Linux/macOS终端执行:
PYTHONPATH=./Problem1:./Problem2 pytest - Windows cmd执行:
set PYTHONPATH=./Problem1;./Problem2 && pytest
该方案不需要修改任何项目文件,仅单次运行生效。
内容的提问来源于stack exchange,提问作者user32882
相关产品推荐
相关产品推荐

