如果多个测试有特定异常,则停止pytest测试

pytest.exit()如果任何测试因特定异常而失败,我想停止使用测试套件。

例如:50 个测试,它们中的任何一个都可能因该异常而在某个时候失败,如果这些测试中至少有 2 个失败超过此异常,我想停止执行。

我试图scope='session'在测试之间保留一个全局计数器(带有 的夹具),并在每次捕获此异常时更新它,但无法在测试之间保持它的值。

有任何想法吗?

回答

这可以通过使用Hooks 来实现。

具体来说,我们将利用两个特定的钩子,pytest_sessionstartpytest_exception_interact. 我们将使用pytest_sessionstart来跟踪我们愿意容忍的特定异常的数量,将其视为存储您提到的“全局计数器”的地方。另一个钩子pytest_exception_interact将用于与失败的测试交互以检查返回的异常类型(如果有)。

conftest.py在测试文件夹的根目录中创建一个文件并放置以下内容:

import pytest


EXC_MAP = {
        ZeroDivisionError: 1,
        KeyError: 1
    }


def pytest_sessionstart(session):
    session.__exc_limits = EXC_MAP


def pytest_exception_interact(node, call, report):
    session = node.session
    type_ = call.excinfo.type

    if type_ in session.__exc_limits:
        if session.__exc_limits[type_] == 0:
            pytest.exit(f"Reached max exception for type: {type_}")
        else:
            session.__exc_limits[type_] -= 1

EXC_MAP是我们愿意在测试调用中允许的异常--> 失败的映射。在pytest_sessionstart钩子中,我们在 上设置了一个私有变量session来跟踪这些变量。在pytest_exception_interact钩子中,我们得到测试引发的异常类型,我们根据阈值检查它,如果该异常的计数达到 0,我们从 退出pytest,跳过剩余的测试。

下面是一个示例测试脚本和终端中的输出。

def foo(a, b):
    return a / b


def test_foo():
    result = foo(1, 0)
    assert result == 1


def test_foo1():
    result = foo(1, 1)
    assert result == 1


def test_foo2():
    result = foo(1, 0)
    assert result == 1


def test_foo3():
    result = foo(1, 1)
    assert result == 1

运行这些时,终端显示:

collected 4 items                                                                                                                                            

test_foo.py F.F

========================================================================== FAILURES ==========================================================================
__________________________________________________________________________ test_foo __________________________________________________________________________

    def test_foo():
>       result = foo(1, 0)

test_foo.py:6: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

a = 1, b = 0

    def foo(a, b):
>       return a / b
E       ZeroDivisionError: division by zero

test_foo.py:2: ZeroDivisionError
_________________________________________________________________________ test_foo2 __________________________________________________________________________

    def test_foo2():
>       result = foo(1, 0)

test_foo.py:16: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

a = 1, b = 0

    def foo(a, b):
>       return a / b
E       ZeroDivisionError: division by zero

test_foo.py:2: ZeroDivisionError
================================================================== short test summary info ===================================================================
FAILED test_foo.py::test_foo - ZeroDivisionError: division by zero
FAILED test_foo.py::test_foo2 - ZeroDivisionError: division by zero
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! _pytest.outcomes.Exit: Reached max exception for type: <class 'ZeroDivisionError'> !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
================================================================ 2 failed, 1 passed in 0.20s =================================================================

我们可以看到它收集了所有 4 个测试,但只运行了其中的 3 个,因为在ZeroDivisionError运行最终测试之前达到了阈值。


以上是如果多个测试有特定异常,则停止pytest测试的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>