Pytest - Fixture作用域混用
- 若测试用例调用多个不同级别的作用域,都会同时生效:
conftest.py
import pytest
"""会话级别fixture,作用域当前目录"""
@pytest.fixture(scope="session")
def login_session():
"""作用于整个py文件"""
print("\n*** session级别的作用域前置操作 ***")
yield
print("*** session级别的作用域后置操作 ***")
test_py.py
import pytest
"""用例级别fixture,作用域单个用例"""
@pytest.fixture(scope="function")
def login_func():
print("\n--- function级别的作用域前置操作 ---")
yield
print("--- function级别的作用域后置操作 ---")
"""类级别fixture,作用域整个类"""
@pytest.fixture(scope="class", autouse=True)
def login_cls():
print("\n=== class级别的作用域前置操作 ===")
yield
print("=== class级别的作用域后置操作 ===")
"""模块级别fixture,作用域整个py文件"""
@pytest.fixture(scope="module")
def login_module():
print("\n^^^ module级别的作用域前置操作 ^^^")
yield
print("^^^ module级别的作用域后置操作 ^^^")
def test_s2(login_session, login_module, login_cls, login_func):
print("\n用例test_s2:在类外的测试用例")
class Test_cls():
def test_s1(self, login_func, login_cls, login_module, login_session):
print("\n用例test_s1:在类中的测试用例")
def test_s3(self, login_func):
print("\n用例test_s3:在类中的测试用例")
if __name__ == '__main__':
pytest.main(['-s', 'test_py.py'])
从执行结果中可以看出(测试用例test_s1,test_s2),不管测试用例调用Fixture函数顺序如何,执行顺序均为(从左到右分别为:先执行 > 后执行):
session > module > class > function
- 执行结果如图所示各级别作用域:
- 黄色框: function
- 紫色框: class
- 蓝色框: module
- 红色框: session
作用域执行顺序
-
如果有多个不同作用域的需要执行,要弄清楚它们将执行的顺序;
-
pytest首先执行范围更高的fixtrue;
-
在请求fixture函数中,先执行较高作用域范围的fixture(session,package,module);
-
再执行在较低作用域的fixture(class,function);
-
test_py.py
import pytest
@pytest.fixture
def func(scope="function"):
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("\nSession")
class TestClass:
# 将作用域的顺序打乱,查看执行结果
def test_s1(self, cls, mod, sess, func, pack):
print("\n测试用例")
if __name__ == "__main__":
pytest.main("-s", "test_py.py")
-
执行顺序结果如图,按照作用域的高至低的顺序为:
- Seesion > Package > Module > Class > Function
作用域依赖关系
-
添加了
@pytest.fixture
,如果fixture还想依赖其他fixture,需要用函数传参的方式:- 当一个函数请求另一个函数时,首先执行另一个函数。
- 如果函数
b
请求函数a
,函数a
将首先执行,因为b
依赖于a
,没有a
就无法运行。 - 即使
b
不需要a
的结果 ,它仍然可以请求a
是否需要,确保在之后执行a
。
test_py.py
import pytest @pytest.fixture() def a(): print("\n第一个Fixture:a") @pytest.fixture() def b(a): print("第二个Fixture:b") @pytest.fixture() def c(a, b): print("第三个Fixture:c") @pytest.fixture() def d(a): print("第四个Fixture:d") @pytest.fixture() def z(d, c): print("第五个Fixture:z") # 测试用例只调用 函数z def test_s1(z): print("\n用例test_s1:Fixture 相互调用") if __name__ == '__main__': pytest.main(['-s', 'test_py.py'])
-
执行依赖关系结果如图:
-
单个fixture被多个fixture调用,只会执行一次;例如函数
a
被函数b、c、d
调用,但只执行了一次; -
优先执行顺序靠前的fixture;例如
def z(d, c):
,优先执行函数d
; -
优先执行最先被调用的
fixture
;例如上述,函数a
为最先被 函数d
调用的,函数d
为最先被 函数z
调用;
-