我正在尝试设置一个项目(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
黑客。
我确定我错过了一些明显的东西。谢谢!
Pytest会将当前目录添加到sys.path
,但这并不一定意味着它可以从源树中导入您的包。事实上,使用src
和test
布局的整个要点是防止pytest对源树进行测试。
您可以通过从项目的顶级目录运行python解释器并尝试导入包来自行检查。它不起作用,除非它已经安装在您的工作环境中。
通过使用src
和test
布局,pytest被迫测试你的软件包的已安装版本。请参阅this great blog post,了解如何以此方式构建项目。这是关键段落:
您将被迫测试已安装的代码(例如:通过在virtualenv中安装)。这将确保部署的代码正常工作(正确打包) - 否则您的测试将失败。早。在您发布损坏的分发之前。
因此,如果您想为项目使用这种布局,则需要在测试之前安装软件包。两种方法都有优点和缺点,但是pytest推荐它,我倾向于同意。
[更新]
作为方便的本地测试的解决方法,您可以使用development mode或setup.py develop
在pip install -e .
中安装包。这使您的包看起来安装在您的环境中,但源树中的任何更新都将立即反映在“已安装”版本中。
如果您选择遵循此方法,则应确保使用沙盒开发环境(例如virtualenv
或conda
),以免污染系统环境。