使 pytest 在 ResourceWarning 上失败(未关闭的文件)

dav*_*ing 7 python pytest

我的一些测试需要确保打开的文件被关闭。让我们用最简单的例子:

# test_example.py
import pytest

@pytest.mark.filterwarnings('error::ResourceWarning')
def test_resourcewarning():
    open('/dev/null')
Run Code Online (Sandbox Code Playgroud)

当我运行时pytest,警告被抛出,甚至打印在测试输出中,但测试仍然通过:

$ pytest
============================ test session starts =============================
platform darwin -- Python 3.10.2, pytest-7.1.1, pluggy-1.0.0
rootdir: /path/to/project
collected 1 item

test_example.py .                                                      [100%]

============================== warnings summary ==============================
test_example.py::test_resourcewarning
  /path/to/python/site-packages/_pytest/unraisableexception.py:78: PytestUnrai
sableExceptionWarning: Exception ignored in: <_io.FileIO [closed]>

  Traceback (most recent call last):
    File "/path/to/project/test_example.py", line 5, in test_resourcewarning
      open('/dev/null')
  ResourceWarning: unclosed file <_io.TextIOWrapper name='/dev/null' mode='r' 
encoding='UTF-8'>

    warnings.warn(pytest.PytestUnraisableExceptionWarning(msg))

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
======================== 1 passed, 1 warning in 0.01s ========================
Run Code Online (Sandbox Code Playgroud)

删除@pytest.mark.filterwarnings或将警告类型更改为不相关的内容(例如DeprecationWarning)会导致测试通过而根本不会打印任何警告,因此显然这捕获了警告 - 但它似乎随后被 pytest 捕获。然后 Pytest 抛出pytest.PytestUnraisableExceptionWarning,这不会失败,因为我没有对此进行过滤。如果我进行过滤,pytest.PytestUnraisableExceptionWarning测试也会通过,因为它不是在寻找原始的ResourceWarning.

我能想到的唯一解决方案是过滤两者:

@pytest.mark.filterwarnings('error::ResourceWarning')
@pytest.mark.filterwarnings('error::pytest.PytestUnraisableExceptionWarning')
Run Code Online (Sandbox Code Playgroud)

但在这一点上,它对我来说没有任何意义,即使在浏览了文档和谷歌搜索结果之后,我也不明白如果 pytest 只是吞下它们并让我捕获它自己的警告,过滤警告应该如何工作警告实际注册测试失败,因此唯一合乎逻辑的结论是我不知道我在做什么(或者这是一个错误)。

我缺少什么?

小智 2

尝试这个:

#test_example.py
import pytest

@pytest.mark.filterwarnings("error")
def test_resourcewarning():
    open('/dev/null')
Run Code Online (Sandbox Code Playgroud)

这使我的测试失败:

在此输入图像描述

取自 pytest 文档(https://docs.pytest.org/en/stable/how-to/capture-warnings.html#pytest-mark-filterwarnings