我通常喜欢pytest警告捕获钩子,因为我可以使用它强制我的测试套件不触发任何警告。但是,我有一项测试,要求将警告打印到stderr才能正常工作。
如何仅对一项测试禁用警告捕获?
例如,类似
def test_warning():
mystderr = StringIO()
sys.stderr = mystderr
warnings.warn('warning')
assert 'UserWarning: warning' in mystderr.getvalue()
(我知道我可以使用capsys
,我只想展示基本思想)
答案 0 :(得分:1)
由于本次讨论的范围有所缩小,我认为这个问题最好命名为“在pytest中,如何在单个测试中捕获警告及其标准错误输出?”。鉴于建议重新措词,我认为答案是“不可能,您需要单独的测试”。
如果没有标准的错误捕获要求,则应该可以使用@pytest.mark.filterwarnings
注释。
@pytest.mark.filterwarnings("ignore")
def test_one():
assert api_v1() == 1
发件人: https://docs.pytest.org/en/latest/warnings.html#pytest-mark-filterwarnings
@wim在评论中指出,这不会捕获警告,而他给出的答案则以标准方式捕获并断言警告。
如果有stderr输出,但没有引发Python警告,capsys将是您所要讲的技术 https://docs.pytest.org/en/latest/capture.html
由于pytest实现的性质,我认为在pytest测试中同时进行这两个步骤都没有意义。
如前所述,pytest将stderr等重定向到内部记录器。其次,它定义了自己的警告处理程序 https://github.com/pytest-dev/pytest/blob/master/src/_pytest/warnings.py#L59
在思想上与该问题的答案相似: https://stackoverflow.com/a/5645133/5729872
我在重新定义warnings.showwarning()
时遇到了一些麻烦,这在Vanilla python中可以正常工作,但是pytest也有意将其重新初始化。
在pytest中不起作用,仅适用于纯Python->
def func(x):
warnings.warn('wwarn')
print(warnings.showwarning.__doc__)
# print('ewarn', file=sys.stderr)
return x + 1
sworig = warnings.showwarning
def showwarning_wrapper(message, category, filename, lineno, file=None, line=None):
"""Local override for showwarning()"""
print('swwrapper({})'.format(file) )
sworig(message,category,filename,lineno,file,line)
warnings.showwarning = showwarning_wrapper
<-在pytest中不起作用,仅适用于纯Python
您可能会在测试用例中放置一个警告处理程序,然后将其输出到stderr ...但这在当时并不能证明所测试的代码。
这是一天结束时的系统。如果考虑到@wim提出的对stderr进行这样的测试可能不会证明太多之后,您决定仍然需要它,我建议将对Python警告对象(python调用程序层)和stderr内容(调用shell)的测试分开层)。第一个测试将仅查看Python警告对象。新的第二个测试用例将通过popen()
或类似名称将被测试的库作为脚本调用,并对所产生的标准错误和输出进行断言。
答案 1 :(得分:-1)
我鼓励您以不同的方式考虑这个问题。
如果要断言某些代码会触发警告,则应使用pytest.warns
上下文。使用match
kwarg检查警告消息,避免尝试从stderr
捕获警告消息带来的额外麻烦。
import re
import warnings
import pytest
def test_warning():
expected_warning_message = "my warning"
match = re.escape(expected_warning_message)
with pytest.warns(UserWarning, match=match):
warnings.warn("my warning", UserWarning)
这应该是测试职责的边缘。测试警告本身导致某些输出输出到stderr上,这不是您的责任,因为该行为来自标准库代码和它应该由Python本身进行测试。