首页 > 编程问答 >为什么“pytest_addoption”钩子不使用配置的“testpaths”运行?

为什么“pytest_addoption”钩子不使用配置的“testpaths”运行?

时间:2024-08-06 03:44:03浏览次数:8  
标签:python pytest

摘要:

我正在尝试使用 pytest_addoption 功能设置自定义 pytest 选项。

但是当在使用所述自定义选项时尝试使用 project.toml 文件配置我的项目时,我得到出现以下错误:

$ pytest --foo foo
ERROR: usage: pytest [options] [file_or_dir] [file_or_dir] [...]
pytest: error: unrecognized arguments: --foo
  inifile: /home/vmonteco/Code/MREs/pytest__addoption__pyproject_toml/01_adding_pyproject.toml/pyproject.toml
  rootdir: /home/vmonteco/Code/MREs/pytest__addoption__pyproject_toml/01_adding_pyproject.toml

尽管配置了测试路径,为什么还是出现此问题?我该如何解决它?

使用的版本是:

  • Python 3.10.13
  • Pytest 8.1.1

如何重现:

第 1 步 - 在组织项目之前,它可以工作:

我在单个目录中从一个非常简单的测试开始。

$ tree
.
├── conftest.py
└── test_foo.py

1 directory, 2 files
$ 
  • conftest.py :
import pytest

def pytest_addoption(parser):
    parser.addoption("--foo", action="store")

@pytest.fixture
def my_val(request):
    return request.config.getoption("--foo")
  • test_foo.py :
def test_foo(my_val):
    assert my_val == "foo"
$ pytest --foo bar
=============================== test session starts ===============================
platform linux -- Python 3.10.13, pytest-8.1.1, pluggy-1.5.0
rootdir: /home/vmonteco/code/MREs/pytest__addoption__pyproject_toml/00_simplest_case
collected 1 item                                                                  

test_foo.py F                                                               [100%]

==================================== FAILURES =====================================
____________________________________ test_foo _____________________________________

my_val = 'bar'

    def test_foo(my_val):
>       assert my_val == "foo"
E       AssertionError: assert 'bar' == 'foo'
E         
E         - foo
E         + bar

test_foo.py:2: AssertionError
============================= short test summary info =============================
FAILED test_foo.py::test_foo - AssertionError: assert 'bar' == 'foo'
================================ 1 failed in 0.01s ================================
$ 

第 2 步 - 添加 || 时|空 并重新组织项目,失败: pyproject.toml 注释:

$ tree
.
├── my_project
│   └── my_tests
│       ├── conftest.py
│       ├── __init__.py
│       └── test_foo.py
└── pyproject.toml

3 directories, 4 files
$ pytest --foo bar
ERROR: usage: pytest [options] [file_or_dir] [file_or_dir] [...]
pytest: error: unrecognized arguments: --foo
  inifile: /home/vmonteco/code/MREs/pytest__addoption__pyproject_toml/01_adding_pyproject_toml/pyproject.toml
  rootdir: /home/vmonteco/code/MREs/pytest__addoption__pyproject_toml/01_adding_pyproject_toml

$ 

有疑问,我还添加了

但我想避免这种情况,我宁愿正确配置我的项目。

第 3 步 - 尝试在

$ pytest --foo bar my_project/my_tests
=============================== test session starts ===============================
platform linux -- Python 3.10.13, pytest-8.1.1, pluggy-1.5.0
rootdir: /home/vmonteco/code/MREs/pytest__addoption__pyproject_toml/01_adding_pyproject_toml
configfile: pyproject.toml
collected 1 item                                                                  

my_project/my_tests/test_foo.py F                                           [100%]

==================================== FAILURES =====================================
____________________________________ test_foo _____________________________________

my_val = 'bar'

    def test_foo(my_val):
>       assert my_val == "foo"
E       AssertionError: assert 'bar' == 'foo'
E         
E         - foo
E         + bar

my_project/my_tests/test_foo.py:2: AssertionError
============================= short test summary info =============================
FAILED my_project/my_tests/test_foo.py::test_foo - AssertionError: assert 'bar' == 'foo'
================================ 1 failed in 0.02s ================================
$

中配置

失败。 testpaths 迄今为止我发现的最好的解释依赖于文档中的以下几点: pyproject.toml 将 pytest_addoption 放在“初始”中的必要性

  • 此钩子仅在初始conftests中调用。| ||pytest_addoption 文档 conftest.py 实际上什么是“

    初始


    ”: 初始conftest是针对每个测试路径的文件,其路径匹配

  • conftest.py 通过加载所有“初始”conftest.py文件: <test_path>/conftest.py 确定测试路径:在命令行上指定,否则在testpaths 如果已定义并从根目录运行,否则为每个测试路径的当前目录 <test_test>/test*/conftest.py ,加载相对于测试路径的目录部分的conftest.py 和test*/conftest.py(如果存在)。在加载conftest.py文件之前,先加载其所有父目录中的conftest.py文件。加载 conftest.py 文件后,递归加载其 pytest_plugins 变量中指定的所有插件(如果存在)。

    1. 工具启动时的插件发现顺序
    • 所以,如果我理解得很好:
    • 我的错误似乎会发生,因为如果我没有提供明确的测试路径,使用当前目录。但在这种情况下,我的

    在树状结构中太深,无法用作初始conftest。

通过我的解决方法,显式传递更深的测试路径可以通过再次使conftest“初始”来解决此问题。

  1. 由此看来,尝试将我的命令行参数路径转换为一些配置( conftest.py )似乎是合适的,如

  2. 相关文档

中所示。 testpaths 但是当尝试再次运行我的命令时,我仍然遇到相同的错误: 我也尝试使用不同类型的配置文件: 但它仍然无法解决问题,尽管等效的命令行参数似乎有效。为什么?

But when trying to run my command again, I still get the same error:

$ cat pyproject.toml
[tool.pytest.ini_options]
testpaths = [
          "my_project/my_tests",
]
$ tree
.
├── my_project
│   └── my_tests
│       ├── conftest.py
│       ├── __init__.py
│       └── test_foo.py
└── pyproject.toml

3 directories, 4 files
$ pytest --foo bar                  
ERROR: usage: pytest [options] [file_or_dir] [file_or_dir] [...]
pytest: error: unrecognized arguments: --foo
  inifile: /home/vmonteco/code/MREs/pytest__addoption__pyproject_toml/02_attempt_to_solve/pyproject.toml
  rootdir: /home/vmonteco/code/MREs/pytest__addoption__pyproject_toml/02_attempt_to_solve

$ 

I also tried to use a different kind of configuration file:

$ cat pytest.ini  
[pytest]
testpaths = my_project/my_tests
$ pytest --foo bar
ERROR: usage: pytest [options] [file_or_dir] [file_or_dir] [...]
pytest: error: unrecognized arguments: --foo
  inifile: /home/vmonteco/code/MREs/pytest__addoption__pyproject_toml/03_with_pytest_ini/pytest.ini
  rootdir: /home/vmonteco/code/MREs/pytest__addoption__pyproject_toml/03_with_pytest_ini

$ 

But it still doesn't solve the problem despite the equivalent as command line argument seems to work. Why?


问题不在于你的 pytest_addoption 钩子,而在于你误解了 testpaths 的作用。

testpaths 选项不会告诉pytest在解析命令行参数 之前 在哪里查找测试。它告诉pytest在 之后 在哪里查找测试,如果没有在命令行上提供任何文件或目录。

发生的事情是,由于你没有在命令行上指定任何测试文件或目录,并且pytest无法识别 --foo 选项,因此它在运行任何测试之前失败,并显示“无法识别的参数”错误。

你有两种选择来解决此问题:

选项 1:始终在命令行上传递测试路径或文件名。 例如:

pytest --foo bar my_project/my_tests/

这很明确,可以让你完全控制要运行哪些测试。

选项 2:使用 addopts 选项在 pyproject.toml pytest.ini 中指定默认测试路径,并在没有提供其他路径时运行。 例如,在 pyproject.toml 中:

[tool.pytest.ini_options]
addopts = "my_project/my_tests/"
testpaths = [
  "my_project/my_tests",
]

这告诉pytest默认运行 my_project/my_tests/ 目录中的测试,除非在命令行上另有指定。

使用这两种方法中的任何一种,你的 pytest_addoption 钩子都应该按预期工作,并且你的自定义 --foo 选项应该可以被识别。

标签:python,pytest
From: 78836105

相关文章

  • 【香橙派系列教程】(七)香橙派下的Python3安装
    【七】香橙派下的Python3安装为接下来的Linux图像识别智能垃圾桶做准备。图像处理使用京东SDK只支持pyhton和Java接口,目的是引入C语言的Python调用,感受大厂做的算法bug此接口是人工智能接口,京东识别模型是通过训练后的模型,精准度取决于训练程度,人工智能范畴在常规嵌入式......
  • vnpy,一个不可思议的Python库!
    vn.py是一个开源的Python交易编程框架,旨在帮助程序员快速搭建属于自己的量化交易平台。该框架支持股票、期货、外汇等多种金融产品的交易,提供了从数据获取、策略开发到交易执行的全流程支持。如何安装vnpy首先,要使用vnpy,您需要通过Python的包管理工具pip来安装它。以下......
  • Python回溯算法
    回溯算法回溯算法是一种系统的搜索算法,用于解决诸如排列组合、子集生成、图的路径、棋盘问题等问题。其核心思想是通过递归尝试各种可能的解决方案,遇到不满足条件的解时则回退(回溯),继续尝试其他可能性,直到找到所有的解决方案或确认无解。主要步骤:选择路径:在当前步骤选择一个可......
  • [python]使用gunivorn部署fastapi服务
    前言Gunicorn是一种流行的WSGIHTTP服务器,常用于部署Django和Flask等PythonWeb框架程序。Gunicorn具有轻量级、高稳定性和高性能等特性,可以轻易提高PythonWSGIApp运行时的性能。基本原理Gunicorn采用了pre-fork模型,也就是一个工作进程和多个worker进程的工作模式。在这个模......
  • python十六进制编辑器
    源代码:importtkinterastkfromtkinterimportfiledialogimportstructimportbinasciiimportosclassHexEditor:def__init__(self,master):self.master=masterself.master.title("十六进制编辑器")self.master.configure(bg......
  • python项目学习 mediapipe手势识别 opencv可视化显示
    importcv2importmediapipeimportnumpydefget_angle(vector1,vector2):#角度计算angle=numpy.dot(vector1,vector2)/(numpy.sqrt(numpy.sum(vector1*vector1))*numpy.sqrt(numpy.sum(vector2*vector2)))#cos(angle)=向量的点乘/向量的模angle=nump......
  • 【优秀python大屏】基于python flask的广州历史天气数据应用与可视化大屏
    摘要气象数据分析在各行各业中扮演着重要的角色,尤其对于农业、航空、海洋、军事、资源环境等领域。在这些领域中,准确的气象数据可以对预测未来的自然环境变化和采取行动来减轻负面影响的决策起到至关重要的作用。本系统基于PythonFlask框架,通过对气象数据的分析和处理来提供......
  • Python-MNE全套教程(官网翻译)-入门01:概述篇
    目的以牺牲深度为代价进行入门学习,简易学习基本方法开始导入相关库:#License:BSD-3-Clause#CopyrighttheMNE-Pythoncontributors.importnumpyasnpimportmne加载数据MNE-Python数据结构式基于fif格式的,但是对于其他格式也有阅读方法,如https://mne.tools/s......
  • Python-MNE全套教程(官网翻译)-入门05:关于传感器位置
    本教程描述了如何读取和绘制传感器位置,以及MNE-Python如何处理传感器的物理位置。像往常一样,我们将从导入我们需要的模块开始:frompathlibimportPathimportmatplotlib.pyplotaspltimportnumpyasnpimportmne关于montage和layout(蒙太奇和传感器布局)montage......
  • Codeforces Round 963 (Div. 2) A - C 详细题解(思路加代码,C++,Python) -- 来自灰名
    比赛链接:Dashboard-CodeforcesRound963(Div.2)-Codeforces之后有实力了再试试后面的题目,现在要做那些题,起码要理解一个多小时题目A:链接:Problem-A-Codeforces题目大意理解:        极少数不考翻译能读懂的cf题目(bushi)每个测试用例第一行一个n,......