【问题标题】:stop pytest tests if several tests have a specific exception如果多个测试有特定异常,则停止 pytest 测试
【发布时间】:2021-02-04 11:14:53
【问题描述】:

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

例如: 50 个测试,其中任何一个测试都可能在某个时候失败并出现该异常,如果这些测试中至少有 2 个测试失败了这个异常,我想停止执行。

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

有什么想法吗?

【问题讨论】:

    标签: python python-3.x pytest fixtures


    【解决方案1】:

    这可以通过使用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_sessionstartpytest_exception_interact 这确实是游戏规则的改变者,谢谢!
    猜你喜欢
    • 2015-02-03
    • 1970-01-01
    • 2020-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多