【pytest-fixture】十四、fixture实例化顺序(执行顺序)详解

我基本上是跟着官网去学习fixture,自己先看并学了一遍,为了方便后续查看和记忆,所以将学习笔记记录下来,如果有不对的地方,欢迎大家评论区指出。

当 pytest 想要执行测试时,一旦它知道将执行哪些夹具,它就必须弄清楚它们将执行的顺序。为此,它考虑了 3 个因素:
  1.范围
  2.依赖关系
  3.自动使用
夹具或测试的名称、定义它们的位置、定义它们的顺序以及请求夹具的顺序与巧合之外的执行顺序无关。虽然 pytest 将尝试确保像这样的巧合在每次运行中保持一致,但这不是应该依赖的东西。如果要控制顺序,最安全的做法是依赖这三样东西,并确保明确建立依赖关系.

1.范围:首先执行范围更高的fixtrue

1.1介绍

在请求fixture函数中,较高作用域范围的fixture(例如ession,package)在较低作用域的fixture(例如function或class)之前执行.

1.2示例代码

文件名: test_demo.py

import pytest


# 默认就是函数级别
@pytest.fixture
def func():
    print("function")


@pytest.fixture(scope="class")
def cls():
    print("class")


@pytest.fixture(scope="module")
def mod():
    print("module")


@pytest.fixture(scope="package")
def pack():
    print("package")


@pytest.fixture(scope="session")
def sess():
    print("session")


class TestClass:
    def test_demo(self, func, cls, mod, pack, sess):
        print("测试用例")

1.3运行结果

在这里插入图片描述

1.4结果分析

我们可以发现sess在请求的时候是在最右边,前面我们讲过,如果是按照从左往右执行,那么就不应该执行session,但实际结果是执行了session,所以我们请求fixture函数时要看它的范围,范围越大的越先执行.

2.依赖关系

2.1介绍

当一个夹具请求另一个夹具时,首先执行另一个夹具。所以如果夹具a请求夹具b,夹具b将首先执行,因为a依赖于b它,没有它就无法运行。即使a 不需要 的结果b,它仍然可以请求b是否需要确保在 之后执行b。

2.2示例代码(官方)

文件名: test_demo.py

import pytest


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


@pytest.fixture
def a(order):
    order.append("a")


@pytest.fixture
def b(a, order):
    order.append("b")


@pytest.fixture
def c(a, b, order):
    order.append("c")


@pytest.fixture
def d(c, b, order):
    order.append("d")


@pytest.fixture
def e(d, b, order):
    order.append("e")


@pytest.fixture
def f(e, order):
    order.append("f")


@pytest.fixture
def g(f, c, order):
    order.append("g")


def test_order(g, order):
    assert order == ["a", "b", "c", "d", "e", "f", "g"]

2.3运行结果

在这里插入图片描述

2.4结果分析

通过最终的断言结果成功来看,我们列表里面的元素顺序就是我们执行的顺序,拿一下官方图
在这里插入图片描述
我们先从测试函数出发,先开始g,g又请求f,依次类推,最后到a,执行了a后在依次返回到b,再到c,再到d.所以夹具依赖也会成为影响顺序的方式之一.

3.自动执行:Autouse fixture首先在其作用域内执行

3.1介绍

当fixture设置了autouse自动执行后,咋它作用域范围内的其他fixtrue之前执行.

3.2代码实例(官方)

文件名: test_demo.py

import pytest


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


@pytest.fixture
def a(order):
    order.append("a")


@pytest.fixture
def b(a, order):
    order.append("b")


@pytest.fixture(autouse=True)
def c(b, order):
    order.append("c")


@pytest.fixture
def d(b, order):
    order.append("d")


@pytest.fixture
def e(d, order):
    order.append("e")


@pytest.fixture
def f(e, order):
    order.append("f")


@pytest.fixture
def g(f, c, order):
    order.append("g")


def test_order_and_g(g, order):
    assert order == ["a", "b", "c", "d", "e", "f", "g"]

3.3运行结果

在这里插入图片描述

3.4结果分析

可以看到结果和依赖关系中的结果一致,但是这里的执行是改变了的,依赖关系中的例子是通过依赖关系到a,b,c,而此示例是没有通过依赖,是直接自动执行的a,b,c.官方图示:
在这里插入图片描述
所以我们设置了自动执行后,在作用域范围内其他fixture之前先执行此fixture函数.

3.5注意

  • 介绍

我们在使用autouse时,我们需要注意很多地方,也是希望能不用就不用,因为不管你是否请求它,它都会自动去帮你执行,下面我们通过官网示例来看

  • 代码示例(官方)
    文件名: test_demo.py
import pytest


@pytest.fixture(scope="class")
def order():
    return []


@pytest.fixture(scope="class", autouse=True)
def c1(order):
    order.append("c1")


@pytest.fixture(scope="class")
def c2(order):
    order.append("c2")


@pytest.fixture(scope="class")
def c3(order, c1):
    order.append("c3")


class TestClassWithC1Request:
    def test_order(self, order, c1, c3):
        assert order == ["c1", "c3"]


class TestClassWithoutC1Request:
    def test_order(self, order, c2):
        assert order == ["c1", "c2"]
  • 运行结果
    在这里插入图片描述
  • 结果分析

我们没有在TestClassWithoutC1Request::test_order中引用c1,但c1也同样执行了,这对我们理解代码有影响,假设自动执行是放在conftest.py中,或者是通过第三方插件引入等等,文件一多,我们就不好看在哪里引用,以至于不知道结果为什么会这样,所以我们能尽量不用就不用,实在要用就在当前文件或者引入文件中去使用.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值