Python 如何在pytest中同时声明UserWarning和SystemExit

Python 如何在pytest中同时声明UserWarning和SystemExit,python,unit-testing,pytest,systemexit,user-warning,Python,Unit Testing,Pytest,Systemexit,User Warning,在pytest中断言UserWarning和SystemExit 在我的应用程序中,我有一个函数,当提供了错误的参数值时,它将从warnings模块引发UserWarnings,然后从sys模块引发SystemExit 代码类似于: def compare_tags(.....): requested_tags = user_requested_tags # as list all_tags = tags_calculated_from_input_file # as lis

在pytest中断言UserWarning和SystemExit

在我的应用程序中,我有一个函数,当提供了错误的参数值时,它将从
warnings
模块引发
UserWarnings
,然后从
sys
模块引发
SystemExit

代码类似于:

def compare_tags(.....):

    requested_tags = user_requested_tags # as list
    all_tags = tags_calculated_from_input_file  # as list 

    non_matching_key = [x for x in requested_tags if x not in all_tags]

    # if user requested non existing tag then raise warning and then exit 
    if len(non_matching_key) > 0:

        # generate warning
        warnings.warn("The requested '%s' keys from '%s' is not present in the input file. Please makes sure the input file has the metadata of interest or remove the non matching keys." %(non_matching_key, given_tags))

        # raise system exit
        sys.exit(0)
为上述功能编写pytest

我想立即在pytest中测试这个
UserWarning
SystemExit
。我可以在pytest as中检查
SystemExit

with pytest.raises(SystemExit):
    compare_tags(....)
但这也会显示一条警告消息(这不是错误)

如果要检查警告,请执行以下操作:

pytest.warns(UserWarning, 
    compare_tags(...)
这将生成一个
SystemExit
错误,因为此调用的函数将触发系统退出


如何将
警告
SystemExit
检查放在同一个pytest中?

您可以嵌套如下两个异常:

def test_exit():
    with pytest.raises(SystemExit):
        error_msg = "warning here"
        with pytest.warns(UserWarning, match = error_msg):
            compare_tags(...)

pytest.warning
pytest.raises
是常用的上下文管理器,当用逗号分隔时,可以在单个
with
语句中声明(请参阅):

这实际上和写作是一样的

with pytest.warns(UserWarning):
    with pytest.raises(SystemExit):
        compare_tags(...)
with pytest.raises(SystemExit):
    with pytest.warns(UserWarning):
        ...
请注意,顺序很重要-当您将两个上下文管理器按相反顺序放置时:

with pytest.raises(SystemExit), pytest.warns(UserWarning):
    ...
这和写作一样

with pytest.warns(UserWarning):
    with pytest.raises(SystemExit):
        compare_tags(...)
with pytest.raises(SystemExit):
    with pytest.warns(UserWarning):
        ...
这里的问题是,
pytest.raises
将捕获所有引发的错误,然后检查捕获的内容。这包括
pytest.warnings
引发的问题。这意味着

with pytest.raises(SystemExit), pytest.warns(UserWarning):
    sys.exit(0)
将通过,因为在
pytest.warning中引发的错误将在
pytest.raises中消失,而

with pytest.warns(UserWarning), pytest.raises(SystemExit):
    sys.exit(0)
将如预期的那样失败