我正在尝试设置一个项目(Python 3.4.4,pytest 3.3.1)来使用pytest,但是pytest无法在文件或目录中运行测试。我认为我使用pytest是错误的,但不是正确的工作流程。
根据"Good Integration Practices"中的建议,并且由于个人偏好将源和测试放在单独的文件夹中,我按如下方式设置了我的项目:
parent_directory/
setup.py
src/
project_name/
__init__.py # empty
utils.py
tests/
__init__.py # empty
project_name/
__init__.py # empty
test_utils.py # has `import project_name.utils.py`
通过这种精确设置,"Usage and Invocations"说我应该可以运行测试 使用
python -m pytest
并且pytest会将当前目录添加到sys.path
(“,但通过python调用也会将当前目录添加到sys.path。”)。如果我尝试从parent_directory/src
执行此操作,则不会收集任何测试(collected 0 items
)。如果我从parent_directory/
执行此操作,则会获得ImportError: No module named 'project_name'
。
some reading之后 - (请参阅“测试根路径”),我发现添加(空{)conftest.py
到src/
“会有pytest识别你的应用程序模块没有指定PYTHONPATH “。
完成此操作后,我可以转到parent_directory/
并成功运行
pytest
和
pytest -k test_some_specific_test_function_name
请注意,我可以从python -m pytest
切换到pytest
,我很高兴。
但是,如果我尝试在特定文件(或目录)中运行测试,例如
pytest tests/project_name/test_utils.py
我再一次得到ImportError: No module named 'project_name'
。这种行为对我来说非常令人惊讶。
我查了一下:
sys.path
“hack”,第二个是环境变量,如果同时处理多个项目,这是不切实际的 - 肯定有更好的方法)允许我保留目录结构的正确工作流程是什么,理想情况下来自parent_directory/
,可以调用所有目录:
pytest
pytest -k test_some_specific_test_function_name
pytest tests/project_name/test_utils.py
没有一些手动sys.path
黑客攻击。
我确定我错过了一些明显的东西。谢谢!
答案 0 :(得分:2)
Pytest 将将当前目录添加到sys.path
,但这并不一定意味着它可以从源树中导入您的包。实际上,使用src
和test
布局的整个要点是阻止 pytest对源树进行测试。
您可以通过从项目的顶级目录运行python解释器并尝试导入包来自行检查。它不起作用,除非它已经安装在您的工作环境中。
通过使用src
和test
布局,pytest将被强制测试已安装的软件包版本。请参阅this great blog post,了解以这种方式构建项目的动机。这是关键段落:
您将被迫测试已安装的代码(例如:通过在virtualenv中安装)。这将确保部署的代码正常工作(正确打包) - 否则您的测试将失败。早。在您发布损坏的发行版之前。
因此,如果您想为项目使用这种布局,则需要在测试之前安装软件包。任何一种方法都有优点和缺点,但pytest推荐它,我倾向于同意。
<强> [更新] 强>
作为方便的本地测试的变通方法,您可以使用setup.py develop
或pip install -e .
在development mode中安装软件包。这使您的包看起来安装在您的环境中,但源树中的任何更新都将立即反映在“已安装”版本中。 1
如果您选择遵循此方法,则应确保使用沙盒开发环境(例如virtualenv
或conda
),以免污染系统环境。
<小时/> 1 您应该知道,如果您的软件包提供了C / C ++或Cython扩展,则需要手动重建它们。