我基本上是跟着官网去学习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中,或者是通过第三方插件引入等等,文件一多,我们就不好看在哪里引用,以至于不知道结果为什么会这样,所以我们能尽量不用就不用,实在要用就在当前文件或者引入文件中去使用.