将 pytest 与 src 层一起使用
Posted
技术标签:
【中文标题】将 pytest 与 src 层一起使用【英文标题】:Using pytest with a src layer 【发布时间】:2018-10-13 19:01:14 【问题描述】:pytest recommends 包括一个额外的目录来分隔项目中的源代码:
my_package
├── src # <-- no __init__.py on this layer
│ └── my_package
│ ├── __init__.py
│ └── util_module
│ ├── __init__.py
│ └── utils.py
└── tests
├── __init__.py
└── test_util_module
├── __init__.py
└── test_utils.py
可悲的是,他们什么也没说[1]关于在这种情况下测试代码中的导入应该如何工作,这在this naive example[2],但使用 pytest 会导致以下错误:
my_package $ pytest
====================== test session starts ======================
platform linux -- Python 3.6.4, pytest-3.5.1, py-1.5.3, pluggy-0.6.0
rootdir: /home/user/workspace/my_package, inifile:
collected 0 items / 1 errors
============================ ERRORS =============================
___ ERROR collecting tests/test_util_module/test_utils.py ___
ImportError while importing test module '/home/user/workspace/my_package/tests/test_util_module/test_utils.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
tests/test_util_module/test_utils.py:1: in <module>
from test.test_module.some_file import starify
E ModuleNotFoundError: No module named 'my_package.util_module'
!!!! Interrupted: 1 errors during collection !!!!!
我可以通过将测试的导入更改为 from src.my_package.util_module.utils import starify
来解决此问题,但随后我的 IDE 抱怨 src
部分是多余的,所以我想保留它。
[1]:不再是这样了。从 3.7.3 版开始,pytest 建议在 @hoefling 的答案中也有可编辑的安装,位于其 good practices 的顶部。
[2]:设置为virtualenv env -p python3.6; source env/bin/activate; pip install pytest
【问题讨论】:
如果您在运行测试之前导出PYTHONPATH=".:src/"
,会改变什么吗?
您是否安装了my_package
,即它是否包含setup.py
?
@NilsWerner 没有,也没有。在测试之前我应该总是这样做吗?我宁愿在构建 CI 之前运行单元测试,但我可能错了。
是的,当然你: 1) 需要构建代码才能对其进行测试。 2)通过安装使包import
able
"当然你:1) 需要构建代码才能对其进行测试。" - 在一般情况下这是不正确的,对于很多人(包括我自己)来说这是不可取的
【参考方案1】:
调整PYTHONPATH
(如 cmets 中所建议的)是解决导入问题的一种可能性。另一个是在src
目录中添加一个空的conftest.py
文件:
$ touch src/conftest.py
而pytest
会将src
添加到sys.path
。这是欺骗pytest
将代码库添加到sys.path
的简单方法。
但是,当您打算构建分发时,通常会选择 src
布局,例如提供 setup.py
并(在这种情况下)明确指定根包目录:
from setuptools import find_packages, setup
setup(
...
package_dir='': 'src',
packages=find_packages(where='src'),
...
)
并在开发模式下安装包(通过python setup.py develop
或pip install --editable .
),而您仍在开发它。这样,您的包 my_package
就可以正确集成到 Python 的站点包结构中,而无需摆弄PYTHONPATH
。
【讨论】:
另外,SO 有一个关于这个主题的excellent answer。 我测试了这两种解决方案并且都有效 =) 感谢您的帮助! 这个官方文档可能会有所帮助:pytest import mechanisms and sys.path/PYTHONPATH【参考方案2】:使用 github 操作时,PYTHONPATH 更新对我不起作用(已知问题)。将这个 pytest-pythonpath 安装与 pytest.ini 文件一起使用对我有用:
pip install pytest-pythonpath # accompany with python_path in pytest.ini, so PYTHONPATH is updated with location for modules under test
有了这个,基本的'pytest'命令很高兴地找到了子目录中的所有测试,并根据我的pytest.ini找到了正在测试的模块(设置为匹配pycharm中的源文件夹)
【讨论】:
以上是关于将 pytest 与 src 层一起使用的主要内容,如果未能解决你的问题,请参考以下文章