我有一个具有以下结构的项目:
Project/
|
+-- src/
| |
| +-- proj/
| |
| +-- __init__.py
| +-- code.py
| +-- tests/
| |
| +-- __init__.py
| +-- conftest.py
| +-- test_code.py
+-- doc/
+-- pytest.ini
+-- setup.py
可导入软件包proj
位于src
目录下。测试与之一同安装在proj.tests
子软件包中。代码,测试本身以及安装都可以正常工作。但是,我无法将选项传递给测试。
我有一个选项--plots
,该选项在conftest.py
(在Project/src/proj/tests/
下)中定义,该选项在根文件夹中创建一个.plots/
文件夹,并进行一些图形调试在那里:
# conftest.py
def pytest_addoption(parser):
parser.addoption("--plots", action="store_true", default=False)
我有两种不同的方式必须运行此测试:
第一个是从命令行进入Project
目录中的:
$ pytest --plots
此操作立即失败
usage: pytest [options] [file_or_dir] [file_or_dir] [...]
pytest: error: unrecognized arguments: --plots
inifile: /.../Project/pytest.ini
rootdir: /.../Project
如果我添加软件包目录,则运行正常:
$ pytest src/proj --plots
...
rootdir: /.../Project, inifile: pytest.ini
...
如果我指定tests子目录,它也会很好:
$ pytest src/proj/tests --plots
...
rootdir: /.../Project, inifile: pytest.ini
...
第二种方法是运行程序包本身的test
函数。 test
函数在Project/src/proj/__init__.py
中定义如下:
# __init__.py
def test(*args, **kwargs):
from pytest import main
cmd = ['--pyargs', 'proj.tests']
cmd.extend(args)
return main(cmd, **kwargs)
该功能旨在像这样安装Project
之后运行:
>>> import proj
>>> proj.test()
通常来说,这可以,但是如果可以,
>>> proj.test('--plots')
我得到和往常一样的错误:
usage: [options] [file_or_dir] [file_or_dir] [...]
: error: unrecognized arguments: --plots
inifile: None
rootdir: /some/other/folder
对于该测试,我先运行python setup.py develop
,然后运行cd
/ {some / other / folder` to
,以确保所有内容均正确安装。
我的目标是当我通过--plots
命令行选项时使两个选项都能正常工作。看来我找到了方法#1的解决方法,该方法是将其中一个软件包手动传递给pytest
,但我什至不完全了解它的工作原理(为什么我可以传递任一{{ 1}}或src/proj
?)。
所以问题是,如何让pytest一致地运行我的测试包,以便正确的src/proj/tests
被选中?我愿意考虑任何可行的替代方案,使我可以使conftest.py
选项在源版本(在--plots
的shell中运行)和Project
版本中均能正常工作。
作为参考,这是我的proj.test()
文件:
pytest.ini
似乎没有什么区别。
我在python 2.7、3.3、3.4、3.5、3.6和3.7(在anaconda中)上使用pytest 3.8.0运行。在所有版本中,结果都是可重复的。
答案 0 :(得分:1)
注意:由于
conftest.py
discovers plugins during startup的方式,此功能仅应在位于测试根目录的插件或pytest
文件中实现。...
请注意,
pytest
在工具启动时未在更深层嵌套的子目录中找到conftest.py
个文件。通常最好将conftest.py
文件保存在顶级测试目录或项目根目录中。
当您从pytest
目录调用Project
时,pytest
将其识别为根目录,因此addoption
中的Project/src/proj/tests/conftest.py
钩子将被忽略。 / p>
如果您描述的项目结构是必需的,则将pytest_addopts
钩子impl移至单独的插件模块;它可以驻留在项目目录中的任何位置,例如Project/src/proj/tests/plugin_plots.py
。现在,如果您致电
$ pytest -p src.proj.tests.plugin_plots
addoption
钩子impl将被执行,并且args将被正确添加。
(您可能需要调整sys.path
才能正确加载自定义插件模块,例如使用PYTHONPATH=. pytest -p
或python -m pytest -p
,或以可编辑模式安装项目等)< / p>
要每次都不输入-p
参数,请将其保留在pytest.ini
中,例如
# pytest.ini
[pytest]
addopts=-p src.proj.tests.plugin_plots
以编程方式运行测试时,增强args列表:
def test(*args, **kwargs):
from pytest import main
cmd = ['-p', 'proj.tests.plugin_plots', '--pyargs', 'proj.tests']
cmd.extend(args)
return main(cmd, **kwargs)
应该可以正常工作。