Pytest fixture机制

通过fixture可以把公共方法参数化,通过@pytest.fixture( )装饰的函数可以作为参数传入到测试用例中,当执行这个测试用例时会优先执行fixture装饰的函数,方便代码复用,减少冗余,可理解成公共方法的封装

场景:在执行把商品加入购物车的测试用例时,先要完成用户登录;接口自动化测试,执行购买时需要传入用户token;

# test_mod8.py
import pytest

@pytest.fixture()
def login():
	print("账号进行登录")

def test_add_shopCar(login):
	print("把商品加入购物车")

 执行结果:

test_mod8.py::test_add_shopCar 账号进行登录
把商品加入购物车
PASSED

=================================================================================== 1 passed in 0.03s ====================================================================================

测试用例 test_add_shopCar中传入参数是login,因此执行test_add_shopCar测试用例时会首先执行login函数

import pytest

@pytest.fixture()
def add_func():
	return 3+2

def test_one(add_func):
	assert add_func > 4

def test_two(add_func):
	assert add_func < 3
test_mod8.py::test_one PASSED
test_mod8.py::test_two FAILED

======================================================================================== FAILURES ========================================================================================

当test_one和test_two测试用例接收 add_func 函数时, fixture的作用是实例化函数, 然后返回add_ func 的值;

在多个测试模块.py中共用一个fixture,可以把fixture移动到conftest.py中,pytest会自动导入,不需要手动导入

 Pytest fixture机制_第1张图片

# conftest.py
import pytest

@pytest.fixture()
def login():
	print("账号进行登录")

@pytest.fixture()
def add_func():
	return 3+2
# test_mod8.py
import pytest

def test_add_shopCar(login):
	print("把商品加入购物车")

def test_one(add_func):
	assert add_func > 4

def test_two(add_func):
	assert add_func < 3

 执行结果:

test_mod8.py::test_add_shopCar 账号进行登录
把商品加入购物车
PASSED
test_mod8.py::test_one PASSED
test_mod8.py::test_two FAILED

======================================================================================== FAILURES ========================================================================================

上述代码,test_mod8.py 模块中test_add_shopCar,test_one, test_two测试函数中入参分别为conftest.py模块中fixture装饰的login(),add_func(),从而实现了fixture装饰下的函数前置功能,可供多个测试模块调用;

fixture 自动导入的顺序: 测试类 > 测试模块 > conftest.py

# conftest.py
import pytest

@pytest.fixture()
def re_str():
	return "这是conftest中的str"
@pytest.fixture()
def re_str():
	return "这是模块中的str"

class TestMod8:

	@pytest.fixture()
	def re_str(self):
		return "这是class中的str"

	def test_three(self,re_str):
		print(re_str)

上述代码分别在测试类,测试模块,conftest.py中定义了re_str并通过@pytest.fixture()装饰

直接通过pytest运行test_three

结果:

test_mod8.py::TestMod8::test_three 这是class中的str
PASSED

=================================================================================== 1 passed in 0.43s ====================================================================================

test_three中的re_str调用的是类中的re_str,如果注释掉类中的re_str再次运行.

 

@pytest.fixture()
def re_str():
	return "这是模块中的str"

class TestMod8:

	# @pytest.fixture()
	# def re_str(self):
	# 	return "这是class中的str"

	def test_three(self,re_str):
		print(re_str)

结果:

test_mod8.py::TestMod8::test_three 这是模块中的str
PASSED

=================================================================================== 1 passed in 0.20s ====================================================================================

当conftest.py中也存在re_str时,测试用例首先执行模块中的re_str,只有当类中的fixture与模块中的fixture都不存在时,才会引用conftest.py中的fixture

fixture中的scope参数

  • fixture为session级别是可以跨.py模块调用的,也就是当我们有多个.py文件的用例的时候,如果多个用例只需调用一次fixture,那就可以设置为scope="session",并且写到conftest.py文件里。
  • package 会作用于包内的每一个测试用例, 且只被调用一次
  • function 每个测试用例都会调用一次
  • class 如果一个class 中有多个测试用例, 在类中只调用一次

fixture中的autouse参数(True, False)

  • 是否自动调用,即测试用例中不需要传入fixture修饰的函数名,也可完成调用
# conftest.py
import pytest

@pytest.fixture(scope="module",autouse=True)
def module_fixture():
	print("这是conftest.py中的module_fixture")
# test_mod8
def test_five():
	print("正在执行测试用例-------test_five")

class TestMod8:

	def test_three(self):
		print("正在执行测试用例-------test_three")

	def test_four(self):
		print("正在执行测试用例-------test_four")

执行结果:

test_mod8.py::test_five 这是conftest.py中的module_fixture
正在执行测试用例-------test_five
PASSED
test_mod8.py::TestMod8::test_three 正在执行测试用例-------test_three
PASSED
test_mod8.py::TestMod8::test_four 正在执行测试用例-------test_four
PASSED

=================================================================================== 3 passed in 0.56s ====================================================================================

任务:

针对上述代码,@pytest.fixture(scope="module",autouse=True) 把scope分别更改为function,class,package再运行

通过 fixture 参数化

# test_mod8.py
import pytest

l = [1,2,3,4,5]
@pytest.fixture(params=l)
def read_params(request):
	s = request.param
	return s

def test_five(read_params):
	x = read_params
	print(f"正在执行测试用例-------test_five,传入参数{x}")

 命令行:pytest -vs test_mod8.py::test_five

结果:
test_mod8.py::test_five[1] 正在执行测试用例-------test_five,传入参数1
PASSED
test_mod8.py::test_five[2] 正在执行测试用例-------test_five,传入参数2
PASSED
test_mod8.py::test_five[3] 正在执行测试用例-------test_five,传入参数3
PASSED
test_mod8.py::test_five[4] 正在执行测试用例-------test_five,传入参数4
PASSED
test_mod8.py::test_five[5] 正在执行测试用例-------test_five,传入参数5
PASSED

=================================================================================== 5 passed in 0.20s ====================================================================================

fixture 中传入的params参数为一个list,fixture装饰的函数传入request参数,通过request.param来遍历params中的元素并返回;

注:params是一个 list 类型

通过fixture + yield 实现setup和teardown

# conftest.py
import pytest

@pytest.fixture(scope="function",autouse=True) #定义这个fixture作用域为每个测试用例都会调用
def function_fixture():
	print("用例执行之前执行,相当于setup")
	yield                                    # yield之前的代码在执行测试用例前执行
                                             # yield之后的代码在执行测试用例后执行
	print("用例执行之后执行,相当于teardown")
import pytest

class TestMod8:

	def test_three(self):
		print("正在执行测试用例-------test_three")

	def test_four(self):
		print("正在执行测试用例-------test_four")

执行结果:

test_mod8.py::TestMod8::test_three 用例执行之前执行,相当于setup
正在执行测试用例-------test_three
PASSED用例执行之后执行,相当于teardown

test_mod8.py::TestMod8::test_four 用例执行之前执行,相当于setup
正在执行测试用例-------test_four
PASSED用例执行之后执行,相当于teardown


=================================================================================== 2 passed in 0.07s ====================================================================================

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(学习python,pytest)