Pytest框架 — 07、Pytest的Fixture(部分前后置)(二)

4、Fixture的相互调用

示例:

import pytest


# 第一层fixture
@pytest.fixture()
def fixture_1():
    data = "fixture_1"
    print("这是第一层fixture")
    return data


# 第二层fixture
@pytest.fixture()
def fixture_2(fixture_1):  # 在这里传递调用第一层fixture
    print("这是第二层fixture")

# 第三层fixture
@pytest.fixture()
@pytest.mark.usefixtures("fixture_1")  # 这种fixture相互调用方式不生效
def fixture_3():
    print("这是第三层fixture")


# 测试类
class TestClass:
    def test_1(self, fixture_1):
        print("调用第1层fixture,返回值为{}".format(fixture_1))

    def test_2(self, fixture_2):
        print("调用第2层fixture,返回值为{}".format(fixture_2))

    def test_3(self, fixture_3):
        print("调用第3层fixture")


"""
执行结果
fixture/use_fixture_each_other.py::TestClass::test_1 这是第一层fixture
调用第1层fixture,返回值为fixture_1
PASSED
fixture/use_fixture_each_other.py::TestClass::test_2 这是第一层fixture
这是第二层fixture
调用第2层fixture,返回值为None
PASSED
fixture/use_fixture_each_other.py::TestClass::test_3 这是第三层fixture
调用第3层fixture
PASSED
"""

示例说明:

  • 在调用存在相互调用的fixture时,执行顺序由底层fixture逐层向上执行(如示例test_2优先执行fixture_1再执行fixture_2
  • 当调用存在相互调用的fixture时,直接被调用的fixture不会将自己接收到的返回值返回给调用方(如示例test_2不会接收到由fixture_1返回的值)
  • 相互调用fixture时不能使用pytest.mark.usefixture装饰器(如示例fixture_3

5、Fixture复用

不同的测试函数可以请求相同的fixture,每个测试函数都会获得该fixture的各自结果。不同的测试函数不互相影响,这样可以保证每个测试函数都能得到干净一致的数据。
示例

import pytest


@pytest.fixture()
def fixture_1():
    return []


def test_1(fixture_1):
    fixture_1.append(0)
    print(f"结果:{fixture_1}")


def test_2(fixture_1):
    fixture_1.append(9)
    print(f"结果:{fixture_1}")

"""
执行结果
fixture/reuse_fixture.py::test_1 结果:[0]
PASSED
fixture/reuse_fixture.py::test_2 结果:[9]
PASSED
"""

示例说明
由上面例子可以看出,两个测试函数都调用了fixture_1,但每次调用返回的结果是一样的,并不会因为test_1fixture_1先添加了0而影响test_2调用的fixture_1返回的结果

6、Fixture缓存返回结果

同一个测试函数多次调用同一个fixture时,第一次执行该fixture函数之后,会把返回结果缓存起来,不会再次执行它们
示例:

import pytest


@pytest.fixture()
def fixture_1():
    print("执行fixture_1")
    return "a"

@pytest.fixture()
def fixture_2():
    print("执行fixture_2")
    return []

@pytest.fixture()
def fixture_append(fixture_1, fixture_2):
    print("执行fixture_append")
    fixture_2.append(fixture_1)

def test_fixture(fixture_append, fixture_2, fixture_1):
    print("执行测试函数")
    print(fixture_2)

"""
执行结果
fixture/fixture_cache.py::test_fixture 执行fixture_1
执行fixture_2
执行fixture_append
执行测试函数
['a']
PASSED

"""

示例说明:
由上面例子可以看出在fixture函数fixture_append中,fixture_1第一次被请求返回字母afixture_2第一次被请求返回空列表,在测试函数test_fixturefixture_2第二次被请求,但返回结果不是不是空列表,而是['a']。如果同一个fixture在同一个测试函数中每次都去请求,那么必然返回的是空列表。

7、Fixture的后置处理

前面的案例都是加了前置处理,相当于setup(),后置teardown()fixture中是可以通过yield关键字和addfinalizer关键字来实现

(一)使用yield关键字实现后置

  1. 示例
import pytest


@pytest.fixture(autouse=True)
def fixture_3():
    print("这是一个前置处理")
    yield
    print("这是一个后置处理")

def testcase_1(fixture_3):
    print("这是测试用例1")

def testcase_2(fixture_3):
    print("这是测试用例2")

"""
执行结果
fixture/use_fixture_3.py::testcase_1 这是一个前置处理
这是测试用例1
PASSED这是一个后置处理

fixture/use_fixture_3.py::testcase_2 这是一个前置处理
这是测试用例2
PASSED这是一个后置处理
"""
  1. 执行顺序
    在前置处理中会根据fixture函数之间的线性关系顺序调用的,后置处理顺序会反过来
import pytest


@pytest.fixture()
def fixture_1():
    print("这是fixture_1")
    return 1

@pytest.fixture()
def fixture_2(fixture_1):
    print("这是fixture_2的【前置】")
    yield 2
    print("这是fixture_2的【后置】")

@pytest.fixture()
def fixture_add(fixture_1, fixture_2):
    print("这是fixture_add的【前置】")
    yield fixture_1 + fixture_2
    print('这是fixture_add的【后置】')

def test_fixture(fixture_2, fixture_add):
    print("这是测试函数")
    assert fixture_add == 3

"""
执行结果
fixture/yiled_order.py::test_fixture 这是fixture_1
这是fixture_2的【前置】
这是fixture_add的【前置】
这是测试函数
PASSED这是fixture_add的【后置】
这是fixture_2的【后置】
"""

(二)使用addfinalizer关键字实现后置

  1. request.addfinalizer把函数变成终结器实现后置处理
import pytest

@pytest.fixture()
def fixture_1(request):
    print("这是fixture_1的【前置】处理")
    def addfinalizer_demo():
        print("这是fixture_1的【后置】处理")

    # 注册后置处理
    request.addfinalizer(addfinalizer_demo)


def test_fixture(fixture_1):
    print("===这是测试函数===")


"""
执行结果
fixture/use_addfinalizer.py::test_fixture 这是fixture_1的【前置】处理
===这是测试函数===
PASSED这是fixture_1的【后置】处理
"""
  1. request.addfinalizer注册多个终结器函数
import pytest

@pytest.fixture()
def fixture_1(request):
    print("这是fixture_1的【前置】处理")

    def addfinalizer_demo_1():
        print("这是fixture_1的【后置】处理1")

    def addfinalizer_demo_2():
        print("这是fixture_2的【后置】处理2")

    # 将多个后置处理函数注册成终结函数
    request.addfinalizer(addfinalizer_demo_1)
    request.addfinalizer(addfinalizer_demo_2)

def test_fixture(fixture_1):
    print("=====这是测试函数=====")


"""
执行结果
fixture/use_more_addfinalizer.py::test_fixture 这是fixture_1的【前置】处理
=====这是测试函数=====
PASSED这是fixture_2的【后置】处理2
这是fixture_1的【后置】处理1
"""
  1. 执行顺序
    由上面注册多个终结器函数示例中可以看到,使用addfinalizer关键字处理后置函数的执行顺序与注册顺序是反的

(三)yield和addfinalizer的区别

区别在于如果fixture中前置出现异常,yield后置不会执行,而addfinalizer后置会执行。

  • 使用yield
import pytest


@pytest.fixture()
def fixture_yield():
    print("这是fixture_yield前置")
    res = 21/0
    yield
    print("这是fixtue_yield后置")



def test_fixture(fixture_yield):
    print("这是测试函数")

"""
执行结果
yield_error.py::test_fixture ERROR                                       [100%]这是fixture_yield前置

test setup failed
@pytest.fixture()
    def fixture_yield():
        print("这是fixture_yield前置")
>       res = 21/0
E       ZeroDivisionError: division by zero

yield_error.py:12: ZeroDivisionError

"""
  • 使用addfinalizer
import pytest


@pytest.fixture()
def fixture_1(request):
    print("这是fixture_1前置")

    def addfinalizer_demo():
        print("这是fixture_1后置")
    request.addfinalizer(addfinalizer_demo)
    res = 21/0

def test_fixture(fixture_1):
    print("这是测试函数")


"""
执行结果
addfinalizer_error.py::test_fixture ERROR                                [100%]这是fixture_1前置

test setup failed
request = <SubRequest 'fixture_1' for <Function test_fixture>>

    @pytest.fixture()
    def fixture_1(request):
        print("这是fixture_1前置")
    
        def addfinalizer_demo():
            print("这是fixture_1后置")
        request.addfinalizer(addfinalizer_demo)
>       res = 21/0
E       ZeroDivisionError: division by zero

addfinalizer_error.py:16: ZeroDivisionError
这是fixture_1后置
"""

从上面yieldaddfinalizer的示例中可以看出yield前置中出现异常,后置处理没有被执行,而addfinalizer的前置中出现异常,并没有影响后置的执行。
注意: 使用addfinalizer一定是后置函数注册成功后出现异常才不会受影响。

参考:https://zhuanlan.zhihu.com/p/355285675

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Pytest框架 — 07、Pytest的Fixture(部分前后置)(二) - Python技术站

(0)
上一篇 2023年4月2日
下一篇 2023年4月2日

相关文章

  • Allure定制报告

    目录 1、定制报告常用的装饰器 2、allure.dynamic在测试方法中动态添加定制 3、用例等级的定制 4、用例描述的定制 5、链接的定制 6、步骤的定制 7、附件的定制 1、定制报告常用的装饰器 结合表和示例图查看 使用方法 参数值 参数说明 @allure.epic() 项目名称 项目名称,树结构第一层 @allure.feature() 模块名称…

    2023年4月2日
    00
  • Pytest框架 — 03、Pytest全局配置文件

    目录 1、Pytest的全局配置文件 (1)说明 (2)示例 (3)常用配置项 (4)执行 1、Pytest的全局配置文件 (1)说明 我们之前用命令行或主函数启动测试的时候会增加一些参数来实现所需功能,很多测试用例执行都需要这些参数,所以在企业中我们会通过全局配置文件的方式来管理这些参数。注意: 全局配置文件的名称是固定的,可以为pytest.ini,to…

    Python开发 2023年4月2日
    00
  • Pytest框架 — 04、Pytest的断言

    目录 1、前言 2、常用断言 3、预期异常断言 4、优化断言提示 5、自定义失败断言提示 1、前言 Pytest使用python自带关键字assert进行断言,断言内容为一个表达式,只要表达式的最终结果为True,那么断言通过,用例执行成功,否则用例执行失败。assert + 表达式 2、常用断言 assert xx:判断xx为真 assert not xx…

    Python开发 2023年4月2日
    00
  • Pytest框架 — 14、Pytest的标记(五)(控制测试用例执行顺序)

    目录 1、前言 2、使用 3、标记最先执行和最后执行 1、前言 在执行自动化测试时,我们通常都希望能够控制执行测试用例的顺序。 在unittest框架中默认按照ACSII码的顺序加载测试用例并执行,顺序为:0~9、A~Z、a~z,测试目录、测试模块、测试类、测试方法/测试函数都按照这个规则来加载测试用例。 在pytest测试框架中,默认从上至下执行,也可以通…

    Python开发 2023年4月2日
    00
  • Pytest框架 — 12、Pytest的标记(三)(重复执行)

    目录 1、前言 2、–count参数使用 (一)在命令行或者main函数使用 (二)在全局配置文件中使用 3、–repeat-scope参数使用 4、@pytest.mark.repeat(count)装饰器使用 5、结合参数x使重复执行在失败时停止 1、前言 在自动化测试的时候我们可能会遇到某些原因,如模块不稳定等,出现一些测试失败,此时我们想要针对单…

    Python开发 2023年4月2日
    00
  • Pytest框架 — 05、setup和teardown(全部前后置)

    目录 1、前言 2、各级别详解 3、总结 1、前言 在自动化测试过程中经常需要进行初始化和后期处理等工作,如电商加购物车测试需要先登录,测试完毕需要关闭浏览器等。Pytest提供了5种类型的setup和teardown的方法,具体如下: 模块级别:setup_module,teardown_module 函数级别:setup_function,teardow…

    Python开发 2023年4月2日
    00
  • Pytest框架 — 09、Pytest的conftest.py文件

    目录 1、conftest.py介绍 2、conftest.py的特点 3、conftest.py文件的使用 4、conftest.py的作用域 1、conftest.py介绍 conftest.py是pytest框架的一种固定写法,把fixture或者自己定义的插件写到这个文件里就会自动去调用。我们前面都是将fixture写到测试用例文件里,在实际工作中更…

    Python开发 2023年4月2日
    00
  • Pytest框架 — 11、Pytest的标记(二)(parametrize参数化)

    目录 1、标记实现参数化 示例1:单个参数 示例2:多个参数 示例3:多个参数化(笛卡尔积) 示例4:ids参数给用例起别名 示例5:使用indirect处理参数值 示例6:标记数据 1、标记实现参数化 通过@pytest.mark.parametrize(argnames, argvalues, indirect=False, ids=None, scop…

    Python开发 2023年4月2日
    00
合作推广
合作推广
分享本页
返回顶部