pytest 覆盖现有的警告过滤器

pytest overrides existing warning filters

提问人:Tom Aldcroft 提问时间:2/4/2023 最后编辑:Tom Aldcroft 更新时间:11/13/2023 访问量:159

问:

似乎忽略警告的使用是不被尊重的。例如:warnings.filterwarningspytest

$ cat test.py
import warnings

warnings.filterwarnings('ignore', category=UserWarning)


def test_warnings_filter():
    warnings.warn("This is a warning", category=UserWarning)

当我运行它时,我希望我的显式忽略的警告将被忽略。相反,我得到这个:pytest

$ pytest test.py
=============================================================================== test session starts ===============================================================================
platform darwin -- Python 3.10.8, pytest-7.2.1, pluggy-1.0.0
rootdir: /Users/aldcroft/tmp/pytest
plugins: anyio-3.6.2
collected 1 item                                                                                                                                                                  

test.py .                                                                                                                                                                   [100%]

================================================================================ warnings summary =================================================================================
test.py::test_warnings_filter
  /Users/aldcroft/tmp/pytest/test.py:7: UserWarning: This is a warning
    warnings.warn("This is a warning", category=UserWarning)

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
========================================================================== 1 passed, 1 warning in 0.01s ===========================================================================

我知道配置文件和标志和,但这些效果不佳 对于我的用例,通过集成测试大量已安装的软件包,其中有 至少有十几个第三方警告,需要忽略这些警告才能获得干净的输出。pytest.ini-W@pytest.mark.filterwarnings<pkg_name>.test()

关于如何做到这一点的任何想法?

Python PyTest 警告

评论

0赞 couteau 2/4/2023
您是否确定它真的是pytest覆盖了您的过滤器,而不是您依赖的第三方软件包?我在测试qgis插件时遇到了类似的问题,并发现qgis覆盖了警告过滤器。
0赞 Tom Aldcroft 2/5/2023
@couteau - 代码示例不会导入任何第三方包,应为您重现该问题。感谢您的帮助。

答:

0赞 Override12 2/6/2023 #1

您可以使用 @pytest.mark.filterwarnings 注释来忽略来自特定测试函数或整个测试类的警告。

import warnings
import pytest

@pytest.mark.filterwarnings("ignore:warning")
def test_warnings_filter():
    warnings.warn("This is a warning", category=UserWarning)

https://docs.pytest.org/en/7.1.x/how-to/capture-warnings.html#pytest-mark-filterwarnings

评论

0赞 Tom Aldcroft 2/6/2023
问题不在于“如何忽略警告”。问题是“为什么 pytest 会忽略使用 Python warnings.filterwarnings() 函数设置的现有过滤器?
1赞 Override12 2/6/2023
@TomAldcroft 您最初的问题中并不清楚,似乎您正在寻找除 pytest.ini 或 -W 以外的任何解决方案。您的问题的答案在 pytest 文档中:docs.pytest.org/en/7.1.x/how-to/...“pytest 不遵循 PEP 506 关于重置所有警告过滤器的建议,因为它可能会破坏通过调用 warnings.simplefilter() 自行配置警告过滤器的测试套件(有关示例,请参阅问题 #2430)。”所以它不适用于 pytest > 3.0.7
0赞 Tom Aldcroft 2/7/2023
感谢您的澄清和链接,这确实有助于我的理解。基本上,我正在寻找的是将现有的警告视为已在 或 中指定。更改方法并编写 pytest 包装器以提供参数大多有效,但遇到了另一个问题,我无法过滤以空格(\n 或空格)开头的警告。想法?pytestwarnings.simplefilter()pytest.ini-W-W
0赞 Kache 11/13/2023 #2

“为什么pytest忽略现有的过滤器”

这可能是由于 pytest 的内置插件用于捕获警告

从版本 3.1 开始,pytest 现在可以在测试执行期间自动捕获警告,并在会话结束时显示它们

如何在运行 pytest 时忽略第三方警告

将 python 中的 in-python 视为应用程序警告配置,pytest 将“忽略”该配置,以便可以独立进行测试警告配置,并牢记测试隔离。warnings.filterwarnings()

你提到过,但pytest也有一个顶级配置,例如在我的:@pytest.mark.filterwarningsfilterwarningspyproject.toml

[tool.pytest.ini_options]
filterwarnings = [
    "ignore:::flask_appbuilder",
    "ignore:::flask_sqlalchemy",
    "ignore:::marshmallow_sqlalchemy",
    "ignore:::pydantic",
]

我忽略了来自这些第三方模块的所有警告。警告过滤器规范和机制来自 Python 核心:https://docs.python.org/3/library/warnings.html#describing-warning-filters

您可能不想要的其他选项

pytest --disable-warnings-- 禁用所有警告,甚至从您的代码中

pytest -p no:warnings-- 完全禁用 pytest 的警告插件,使你的测试警告配置与你的应用程序警告配置相同。如果您只想静音第三方警告,并且永远不会发出自己的警告,这可能没问题。但是,如果您正在编写库并希望警告用户(因为您需要测试该行为),则可能需要使用警告插件。