pytest解读fixtures之Teardown处理yield和addfinalizer方案

 更新时间:2022年06月06日 10:11:14   作者:把苹果咬哭的测试笔记  
这篇文章主要为大家介绍了pytest解读fixtures之Teardown处理yield和addfinalizer的方案实例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

前言

当我们运行测试函数时,我们希望确保测试函数在运行结束后,可以自己清理掉对环境的影响。这样的话,它们就不会干扰任何其他的测试函数,更不会日积月累的留下越来越多的测试数据。

用过unittest的朋友相信都知道teardown这个函数,做的是一样的事情,那么下面姑且就把这种“善后”工作的代码叫做teardown代码吧。

而pytest中的fixture,也提供了这样一个非常有用的系统,我们可以在里面定义teardown代码。

这里可以使用2种方式来实现,分别是yieldaddfinalizer

一、yield fixtures(推荐)

1, yield 和 return

在有yield的fixtures函数中,关键字yield 可以代替 return,可以把fixture里的一些对象传递给调用它们的fixture函数或者测试函数。

就像其他普通的fixture函数一样。区别仅仅是:

  • yield替换掉了return
  • teardown代码放置在yield之后

2, yield的执行顺序

pytest在执行fixture函数时,会根据fixture函数之间的线性关系顺序调用的。但是,当测试函数运行结束的时候,pytest又会按照之前的顺序反方向来执行fixture中yield之后的代码。

结合示例看下,这里没有引用官方示例了,手写一个直观些的:

import pytest
@pytest.fixture
def fixture_one():
    print("\n执行fixture_one")
    return 1
@pytest.fixture
def fixture_two(fixture_one):
    print("\n执行fixture_two")
    yield 2
    print("\n执行fixture_two的teardown代码")
@pytest.fixture
def fixture_adding(fixture_one, fixture_two):
    print("\n执行fixture_adding")
    result = fixture_one + fixture_two
    yield result
    print("\n执行fixture_adding的teardown代码")
def test_demo(fixture_two, fixture_adding):
    print("\n执行测试函数test_demo")
    assert fixture_adding == 3

代码中,fixture中调用多个fixture,测试函数中调用多个fixture,通过前面几章的接触,相信大家这时候已经可以梳理出前后调用顺序了:

  • test_demo 测试函数,先去调用fixture函数 fixture_two,然后调用 fixture_adding。
  • 在fixture函数 fixture_two中,又会去调用另一个fixture函数 fixture_one。
  • 在fixture函数 fixture_adding中,调用了 fixture_one、fixture_two。

所以,fixture函数的先后顺序是:fixture_onefixture_twofixture_adding。那么,可以得知测试结束后的teardown代码执行顺序:fixture_addingfixture_two

运行一下代码,验证下结果是否符合我们的梳理:

============================= test session starts =============================
platform win32 -- Python 3.6.8, pytest-5.4.3, py-1.9.0, pluggy-0.13.1
rootdir: D:\练习\demo_fixture
plugins: allure-pytest-2.8.32, celery-4.3.0, Faker-4.14.2, base-url-1.4.2, html-2.1.1, metadata-1.10.0collected 1 item
test_module.py 
执行fixture_one
执行fixture_two
执行fixture_adding
.
执行测试函数test_demo
执行fixture_adding的teardown代码
执行fixture_two的teardown代码
                                                         [100%]
============================== 1 passed in 0.09s ==============================

结果与我们刚才梳理的一致。

但是,值得注意的是,就算是teardown的代码是按照正确的顺序执行,也不能保证代码能正常执行的。比如说teardown里的某些代码执行异常了,导致别的清理动作也没法执行。这里就涉及到另一个点了:健壮的fixture结构应该是什么样子。这个官方文档另起进行说明,这里同样。

二、addfinalizer

1.request.addfinalizer把函数变成终结器

在pytest中想要做teardown的处理,除了使用带有yield的fixture函数,还可以直接添加终结器。直接来看示例代码:

import pytest
@pytest.fixture()
def demo_fixture(request):
    print("\n这个fixture在每个case前执行一次")
    def demo_finalizer():
        print("\n在每个case完成后执行的teardown")
    #注册demo_finalizer为终结函数    
    request.addfinalizer(demo_finalizer)
def test_01(demo_fixture):
    print("\n===执行了case: test_01===")
def test_02(demo_fixture):
    print("\n===执行了case: test_02===")

看下运行结果:

============================= test session starts =============================
platform win32 -- Python 3.6.8, pytest-5.4.3, py-1.9.0, pluggy-0.13.1
rootdir: D:\练习\demo_fixture
plugins: allure-pytest-2.8.32, celery-4.3.0, Faker-4.14.2, base-url-1.4.2, html-2.1.1, metadata-1.10.0collected 2 items
test_module.py 
这个fixture在每个case前执行一次
.
===执行了case: test_01===
在每个case完成后执行的teardown
这个fixture在每个case前执行一次
.
===执行了case: test_02===
在每个case完成后执行的teardown
                                                        [100%]
============================== 2 passed in 0.10s ==============================
Process finished with exit code 0

运行结果可以看出,效果与yield是一致的。这算是一个固定写法,关于request文档中也有另外的讲解,届时再分享。

2.request.addfinalizer注册多个终结器函数

上方代码是一个终结函数,如果要注册多个呢?

import pytest
@pytest.fixture()
def demo_fixture(request):
    print("\n这个fixture在每个case前执行一次")
    def demo_finalizer():
        print("\n在每个case完成后执行的teardown")
    def demo_finalizer2():
        print("\n在每个case完成后执行的teardown2")
    #注册demo_finalizer为终结函数
    request.addfinalizer(demo_finalizer)
    request.addfinalizer(demo_finalizer2)
def test_01(demo_fixture):
    print("\n===执行了case: test_01===")
def test_02(demo_fixture):
    print("\n===执行了case: test_02===")
if __name__ == '__main__':
    pytest.main(['-s', 'test_module.py'])

运行结果:

============================= test session starts =============================
platform win32 -- Python 3.6.8, pytest-5.4.3, py-1.9.0, pluggy-0.13.1
rootdir: D:\练习\demo_fixture
plugins: allure-pytest-2.8.32, celery-4.3.0, Faker-4.14.2, base-url-1.4.2, html-2.1.1, metadata-1.10.0collected 2 items
test_module.py 
这个fixture在每个case前执行一次
.
===执行了case: test_01===
在每个case完成后执行的teardown2
在每个case完成后执行的teardown
这个fixture在每个case前执行一次
.
===执行了case: test_02===
在每个case完成后执行的teardown2
在每个case完成后执行的teardown
                                                        [100%]
============================== 2 passed in 0.09s ==============================
Process finished with exit code 0

这里要注意的是,多个终结器的情况下,执行的顺序是与注册时候相反的。

3.yield和addfinalizer的区别

目前从官方文档中看到的是

We have to be careful though, because pytest will run that finalizer once it’s been added, even if that fixture raises an exception after adding the finalizer. 

一旦添加了终结器,pytest便会执行。

但是,当我尝试在setup代码中进行抛错,终结器的代码却并没有执行。

尝试搜索外网暂时也没得到有效的帮助,只能在GitHub上向pytest提了issue了,这里算是埋下一个坑,待后续解决,更多关于Teardown处理yield addfinalizer的资料请关注脚本之家其它相关文章!

相关文章

  • Python从PDF中提取文本的方法效率总结

    Python从PDF中提取文本的方法效率总结

    日常工作中我们经常会用到pdf格式的文件,大多数情况下是浏览或者编辑pdf信息,但有时候需要提取pdf中的文本,这篇文章主要给大家总结介绍了关于Python从PDF中提取文本的方法效率,需要的朋友可以参考下
    2023-09-09
  • Python数据分析中常见统计方法详解

    Python数据分析中常见统计方法详解

    数据分析是现代社会中不可或缺的一部分,通过对数据的统计和分析,我们可以得出有用的信息和见解,本文将介绍在 Python 中常见的数据统计方法,希望对大家有所帮助
    2024-02-02
  • 详细介绍Python中的set集合

    详细介绍Python中的set集合

    本文详细介绍了Python中set集合的基本概念和详细用法,希望对读者朋友们有所帮助。需要的朋友可以参考下面具体的文章内容
    2021-09-09
  • python numpy矩阵信息说明,shape,size,dtype

    python numpy矩阵信息说明,shape,size,dtype

    这篇文章主要介绍了python numpy矩阵信息说明,shape,size,dtype,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-05-05
  • python顺序执行多个py文件的方法

    python顺序执行多个py文件的方法

    今天小编大家分享一篇python顺序执行多个py文件的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-06-06
  • numpy.random模块用法总结

    numpy.random模块用法总结

    这篇文章主要介绍了numpy.random模块用法总结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-05-05
  • python中sklearn库predict及python sklearn linearmodel(安装过程)

    python中sklearn库predict及python sklearn linearmodel(

    Scikit-learn(sklearn)是机器学习中常用的第三方模块,对常用的机器学习方法进行了封装,包括回归(Regression)、降维(Dimensionality Reduction)、分类(Classfication)、聚类(Clustering)等方法,今天小编给大家分享python中sklearn库predict的问题,感兴趣的朋友一起看看吧
    2024-02-02
  • Python列表insert()函数用法详解

    Python列表insert()函数用法详解

    这篇文章主要介绍了Python列表insert()函数的使用方法,文章通过代码示例介绍的非常详细,对我们学习或工作有一定的参考价值,需要的朋友可以参考下
    2023-07-07
  • Python3 pandas 操作列表实例详解

    Python3 pandas 操作列表实例详解

    这篇文章主要介绍了Python3 pandas 操作列表实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-09-09
  • Playwright中如何保持登录状态

    Playwright中如何保持登录状态

    本文主要介绍了Playwright中如何保持登录状态,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-12-12

最新评论