Pytest----如何使用fixture中addfinalizer解决yield的缺陷

DevOps技术社区 2022-08-28 03:15:43

目录

  • 一、yield的缺陷
  • 二、request的addfinalizer的使用方法
  • 三、yield缺陷另外一种解决方案

一、yield的缺陷

首先看下如下例子,test_demo.py内容如下:

import pytest

@pytest.fixture(autouse=True,scope="function")
def function_fixture():
    print("\nin function_fixture setup ...")
    a=1/0
    yield 10
    print("\nin function_fixture teardown ...")

def test_func3(function_fixture):
    print("in test_func3...")
    assert function_fixture == 11

执行结果如下,仔细观察就会发现,当在setup部分出错了,则teardown部分根本就不会执行了,这一点对于自动化测试来讲是有一定弊端的,比如在setup部分配置了一些基础数据,然后由于某种原因出错了,这样由于根本不会执行teardown的操作,从而导致整体环境就有残留了,这就是yield关键字存在的弊端

$ pytest -s
========================================================================= test session starts ==========================================================================
platform win32 -- Python 3.9.7, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: D:\src\blog\tests, configfile: pytest.ini
plugins: allure-pytest-2.9.43, caterpillar-pytest-0.0.2, hypothesis-6.31.6, forked-1.3.0, rerunfailures-10.1, xdist-2.3.0
collected 1 item                                                                                                                                                        

test_demo.py
in function_fixture setup ...
E

================================================================================ ERRORS ================================================================================
_____________________________________________________________________ ERROR at setup of test_func3 _____________________________________________________________________

    @pytest.fixture(autouse=True,scope="function")
    def function_fixture():
        print("\nin function_fixture setup ...")
>       a=1/0
E       ZeroDivisionError: division by zero

test_demo.py:6: ZeroDivisionError
======================================================================= short test summary info ========================================================================
ERROR test_demo.py::test_func3 - ZeroDivisionError: division by zero
=========================================================================== 1 error in 0.10s ===========================================================================

二、request的addfinalizer的使用方法

如下,通过request的addfinalizer则可以解决这个问题

test_demo.py内容如下:

import pytest

@pytest.fixture(autouse=True,scope="function")
def function_fixture(request):

    def teardown_op():
        print("\nin function_fixture teardown ...")
    request.addfinalizer(teardown_op)
    print("\nin function_fixture setup ...")
    a=10/0
    return 10


def test_func3(function_fixture):
    print("in test_func3...")
    assert function_fixture == 11

执行结果如下,可以发现虽然setup部分虽然出错了,但是teardown仍然可以正常执行

pytest -s
========================================================================= test session starts ==========================================================================
platform win32 -- Python 3.9.7, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: D:\src\blog\tests, configfile: pytest.ini
plugins: allure-pytest-2.9.43, caterpillar-pytest-0.0.2, hypothesis-6.31.6, forked-1.3.0, rerunfailures-10.1, xdist-2.3.0
collected 1 item                                                                                                                                                        

test_demo.py
in function_fixture setup ...
E
in function_fixture teardown ...


================================================================================ ERRORS ================================================================================
_____________________________________________________________________ ERROR at setup of test_func3 _____________________________________________________________________

request = <SubRequest 'function_fixture' for <Function test_func3>>

    @pytest.fixture(autouse=True,scope="function")
    def function_fixture(request):

        def teardown_op():
            print("\nin function_fixture teardown ...")
        request.addfinalizer(teardown_op)
        print("\nin function_fixture setup ...")
>       a=10/0
E       ZeroDivisionError: division by zero

test_demo.py:10: ZeroDivisionError
======================================================================= short test summary info ========================================================================
ERROR test_demo.py::test_func3 - ZeroDivisionError: division by zero
=========================================================================== 1 error in 0.10s ===========================================================================

三、yield缺陷另外一种解决方案

上面的优化能解决teardown不执行的问题,但是还有另外的问题,比如setup有5个步骤,teardown有对应的5个步骤,则按照上面的解决办法带来一个问题是比如setup中在第二个步骤中报错了,则此时相当于setup只成功执行了一个步骤,而上述解决方案中的teardown中不得不把5个步骤全部执行,这在一些场景中也是有问题的

为了解决上面的问题,下面的解决方案则可能稍微更好一些,即还是使用yield关键字,不过每一个fixture的setup只做原子操作,teardown也只做与setup对应的原子操作,如下代码中f1,f2,f3中的setup和teardown分别只做原子操作,假设在f2的setup中由于某种原因出错,此时f2因为setup报错了,因此f2没有必要执行teardown,而采用这种方案即使f2中setup失败了,f1的teardown仍然执行,如此则达到了只要setup成功了就会执行其对应的teardown操作

如下test_demo.py代码如下:

import pytest

@pytest.fixture(scope="function")
def f1():
    print("\nin f1 fixture setup...")
    yield
    print("\nin f1 fixture teardown...")

@pytest.fixture(scope="function")
def f2(f1):
    print("\nin f2 fixture setup...")
    a=1/0
    yield
    print("\nin f2 fixture teardown...")

@pytest.fixture(scope="function")
def f3(f2):
    print("\nin f3 fixture setup...")
    yield 10
    print("\nin f3 fixture teardown...")

def test_func3(f3):
    print("\nin test_func3...")
    assert f3 == 11

执行结果如下:

$ pytest -s
========================================================================= test session starts ==========================================================================
platform win32 -- Python 3.9.7, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: D:\src\blog\tests, configfile: pytest.ini
plugins: allure-pytest-2.9.43, caterpillar-pytest-0.0.2, hypothesis-6.31.6, forked-1.3.0, rerunfailures-10.1, xdist-2.3.0
collected 1 item                                                                                                                                                        

test_demo.py
in f1 fixture setup...

in f2 fixture setup...
E
in f1 fixture teardown...


================================================================================ ERRORS ================================================================================
_____________________________________________________________________ ERROR at setup of test_func3 _____________________________________________________________________

f1 = None

    @pytest.fixture(scope="function")
    def f2(f1):
        print("\nin f2 fixture setup...")
>       a=1/0
E       ZeroDivisionError: division by zero

test_demo.py:12: ZeroDivisionError
======================================================================= short test summary info ========================================================================
ERROR test_demo.py::test_func3 - ZeroDivisionError: division by zero
=========================================================================== 1 error in 0.10s ===========================================================================

...全文
387 回复 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

32

社区成员

发帖
与我相关
我的任务
社区描述
围绕测试开发、Devops、软件工程等方向,学习交流,共享技术新动态、新方向。求助工作中的问题,困惑等,互相交流,共同成长
软件工程测试工具devops 技术论坛(原bbs) 江苏省·南京市
社区管理员
  • redrose2100
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

1、社区话题和文章主要围绕DevOps技术栈

2、有广告需求请联系微信 Redrose2100

 

试试用AI创作助手写篇文章吧