Mad*_*ist 6 python testing pytest
我有一个具有以下结构的项目:
Project/
|
+-- src/
| |
| +-- proj/
| |
| +-- __init__.py
| +-- code.py
| +-- tests/
| |
| +-- __init__.py
| +-- conftest.py
| +-- test_code.py
+-- doc/
+-- pytest.ini
+-- setup.py
Run Code Online (Sandbox Code Playgroud)
可导入的包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)
Run Code Online (Sandbox Code Playgroud)
我想有两种不同的方式来运行这个测试:
第一个是从命令行,在Project目录中:
$ pytest --plots
Run Code Online (Sandbox Code Playgroud)
这立即失败
usage: pytest [options] [file_or_dir] [file_or_dir] [...]
pytest: error: unrecognized arguments: --plots
inifile: /.../Project/pytest.ini
rootdir: /.../Project
Run Code Online (Sandbox Code Playgroud)
如果我添加包目录,运行正常:
$ pytest src/proj --plots
...
rootdir: /.../Project, inifile: pytest.ini
...
Run Code Online (Sandbox Code Playgroud)
如果我指定测试子目录,它也很顺利:
$ pytest src/proj/tests --plots
...
rootdir: /.../Project, inifile: pytest.ini
...
Run Code Online (Sandbox Code Playgroud)
第二种方式是运行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)
Run Code Online (Sandbox Code Playgroud)
该功能旨在Project像这样安装后运行:
>>> import proj
>>> proj.test()
Run Code Online (Sandbox Code Playgroud)
一般来说,这工作正常,但如果我这样做
>>> proj.test('--plots')
Run Code Online (Sandbox Code Playgroud)
我像往常一样得到同样的错误:
usage: [options] [file_or_dir] [file_or_dir] [...]
: error: unrecognized arguments: --plots
inifile: None
rootdir: /some/other/folder
Run Code Online (Sandbox Code Playgroud)
对于这个测试,我跑了python setup.py develop然后cd'd to/some/other/folder` 以确保一切安装正确。
我的目标是当我传入--plots命令行选项时让两个选项都能正常工作。似乎我已经找到了选项 #1 的解决方法,即手动将其中一个包传递到pytest,但我什至不完全理解它是如何工作的(为什么我可以传入src/proj或src/proj/tests?)。
所以问题是,如何让 pytest 始终如一地运行我的测试包,以便选择正确的包conftest.py?我愿意考虑任何合理的替代方案,使我能够使该--plots选项在源代码(在来自 的 shell 中运行Project)版本和proj.test()版本中始终如一地工作。
作为参考,这是我的pytest.ini文件:
# pytest.ini
[pytest]
testpaths = src/proj/tests
confcutdir = src/proj/tests
Run Code Online (Sandbox Code Playgroud)
它似乎没有任何区别。
我在 Python 2.7、3.3、3.4、3.5、3.6 和 3.7(在 anaconda 中)上运行 pytest 3.8.0。在所有版本中,结果都是可重现的。
注意:
conftest.py由于pytest在启动期间如何发现插件,此功能应仅在位于测试根目录的插件或文件中实现。...
请注意,在工具启动时
pytest不会conftest.py在更深的嵌套子目录中找到文件。将conftest.py文件保存在顶级测试或项目根目录中通常是个好主意。
当您pytest从Project目录调用时,pytest将其识别为根目录,因此会忽略addoption挂钩Project/src/proj/tests/conftest.py。
如果您描述的项目结构是pytest_addopts必需的,我会将钩子 impl移动到单独的插件模块;这可以驻留在项目目录中的任何位置,例如Project/src/proj/tests/plugin_plots.py. 现在,如果你打电话
$ pytest -p src.proj.tests.plugin_plots
Run Code Online (Sandbox Code Playgroud)
该addoption钩IMPL将被执行的Args将被正确地加入。
(您可能需要调整sys.path才能正确加载自定义插件模块,例如使用PYTHONPATH=. pytest -p或python -m pytest -p,或以可编辑模式安装项目等)
-p要不每次都输入arg,请将其持久化pytest.ini,例如
# pytest.ini
[pytest]
addopts=-p src.proj.tests.plugin_plots
Run Code Online (Sandbox Code Playgroud)
以编程方式运行测试时,请增强 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)
Run Code Online (Sandbox Code Playgroud)
应该工作得很好。