【pytest官方文档】解读fixtures - 7. Teardown处理,yield和addfinalizer

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

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

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

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

一、yield fixtures(推荐)

1,yield 和 return

在有yield的fixtures函数中,关键字yield 可以代替 return,可以把fixture里的一些对象传递给调用它们的fixture函数或者测试函数。
就像其他普通的fixture函数一样。区别仅仅是:

  1. yield替换掉了return
  2. 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,通过前面几章的接触,
相信大家这时候已经可以梳理出前后调用顺序了:

  1. test_demo 测试函数,先去调用fixture函数 fixture_two,然后调用 fixture_adding。
  2. 在fixture函数 fixture_two中,又会去调用另一个fixture函数 fixture_one。
  3. 在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,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,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了,这里算是埋下一个坑,待后续解决。

当晚坑已填,点击此处跳转

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


目录1、前言2、mark的使用(一)注册自定义标记(二)在测试用例上标记(三)执行3、扩展(一)在同一个测试用例上使用多个标记(二)在测试类上使用标记1、前言在自动化测试工作中我们有时候并不需要测试所有的测试用例,比如在冒烟测试阶段,我们只需要测试基本功能是否正常就可以了。在pytest中提供
用例执行状态用例执行完成后,每条用例都有自己的状态,常见的状态有passed:测试通过failed:断言失败error:用例本身写的质量不行,本身代码报错(譬如:fixture不存在,fixture里面有报错)xfail:预期失败,加了 @pytest.mark.xfail()  error的栗子一:参数不存在 defpwd():prin
什么是conftest.py可以理解成一个专门存放fixture的配置文件 实际开发场景多个测试用例文件(test_*.py)的所有用例都需要用登录功能来作为前置操作,那就不能把登录功能写到某个用例文件中去了 如何解决上述场景问题?conftest.py的出现,就是为了解决上述问题,单独管理一些全局的
前言pytest默认执行用例是根据项目下的文件名称按ascii码去收集运行的;文件中的用例是从上往下按顺序执行的。pytest_collection_modifyitems这个函数顾名思义就是收集测试用例、改变用例的执行顺序的。【严格意义上来说,我们在用例设计原则上用例就不要有依赖顺序,这样才能更好
当我们对测试用例进行参数化时,使用@pytest.mark.parametrize的ids参数自定义测试用例的标题,当标题中有中文时,控制台和测试报告中会出现Unicode编码问题,这看起来特别像乱码,我们想让中文正常展示出来,需要用到pytest框架的钩子函数pytest_collection_modifyitems。先看问题:#file_n
前言:什么是元数据?元数据是关于数据的描述,存储着关于数据的信息,为人们更方便地检索信息提供了帮助。pytest框架里面的元数据可以使用pytest-metadata插件实现。文档地址https://pypi.org/project/pytest-metadata/未安装插件pytest-metadata之前执行:环境搭建:使用
前言前面一篇讲了setup、teardown可以实现在执行用例前或结束后加入一些操作,但这种都是针对整个脚本全局生效的如果有以下场景:用例1需要先登录,用例2不需要登录,用例3需要先登录。很显然无法用setup和teardown来实现了fixture可以让我们自定义测试用例的前置条件 
前言:写完一个项目的自动化用例之后,发现有些用例运行较慢,影响整体的用例运行速度,于是领导说找出运行慢的那几个用例优化下。--durations参数可以统计出每个用例运行的时间,对用例的时间做个排序。pytest-h查看命令行参数,关于--durations=N参数的使用方式--durations=N
钩子函数之pytest_addoption介绍:①pytest_addoption钩子函数可以让用户注册一个自定义的命令行参数,以便于用户在测试开始前将数据从外部(如:控制台)传递给程序;【程序根据获取的用户传递的自定义的参数值来做一些事情】②pytest_addoption钩子函数一般和内置fixturepytestcon
[pytest]#命令行参数----空格分隔,可添加多个命令行参数-所有参数均为插件包的参数addopts=-s-reruns1--html=..eporteport.html#测试路径----当前目录下的scripts文件夹-可自定义testpaths=../scripts#搜索文件名----当前目录下的scripts文件夹下,以test_开头,以.py
python通用测试框架大多数人用的是unittest+HTMLTestRunner,这段时间看到了pytest文档,发现这个框架和丰富的plugins很好用,所以来学习下pytest. image.pngpytest是一个非常成熟的全功能的Python测试框架,主要有以下几个特点:简单灵活,容易上手支持参数化能够支持简单的单
1、装饰器,放在函数前面,跳过用例 @pytest.mark.skip(reason="nowayofcurrentlytestingthis")importpytestdeftest1():print('操作1')print("-----------------------------------------------")@pytest.mark.skip(reason="nowayofcur
本文实例为大家分享了python下载微信公众号相关文章的具体代码,供大家参考,具体内容如下目的:从零开始学自动化测试公众号中下载“pytest"一系列文档1、搜索微信号文章关键字搜索2、对搜索结果前N页进行解析,获取文章标题和对应URL主要使用的是requests和bs4中的Beautifulsoup
From:https://www.jianshu.com/p/54b0f4016300一.fixture介绍fixture是pytest的一个闪光点,pytest要精通怎么能不学习fixture呢?跟着我一起深入学习fixture吧。其实unittest和nose都支持fixture,但是pytest做得更炫。fixture是pytest特有的功能,它用pytest.fixture标识,定义在函
参数化有两种方式:1、@pytest.mark.parametrize2、利用conftest.py里的pytest_generate_tests 1中的例子如下:@pytest.mark.parametrize("test_input,expected",[("3+5",8),("2+4",6),("6*9",42)])deftest_eval(test_input,expected):
pytest优于其他测试框架的地方:1、简单的测试可以简单的写2、复杂的测试也可以简单的写3、测试的可读性强4、易于上手5、断言失败仅使用原生assert关键字,而不是self.assertEqual()或者self.assertLessThan()6、pytest可以运行有unitest和nose编写的测试用例pytest不依赖pyth
学习python的pytest框架需要的基础知识和学习准备测试从业者学习python应该掌握的内容:首先是变量和数据类型,其次列表、字典以及Json的一些处理,再者就是循环判断以及函数或类这些内容。其中的重点:1.循环判断以及字典这块是重点2.函数和类,类的学习这块要花较多时间去学
前言pytest可以支持自定义标记,自定义标记可以把一个web项目划分多个模块,然后指定模块名称执行。app自动化的时候,如果想android和ios公用一套代码时,也可以使用标记功能,标明哪些是ios用例,哪些是android的,运行代码时候指定mark名称运行就可以mark标记1.以下用例,标记test_send_http(
unittest参考文档: https://docs.python.org/3/library/unittest.htmlunittest笔记TheunittestunittestingframeworkwasoriginallyinspiredbyJUnitandhasasimilarflavorasmajorunittestingframeworksinotherlanguages.Itsupportstestautomation,shar
fixture场景一:参数传入代码如下:运行结果: