pytest-fixture简介及其用法讲解
本文深入解析pytest框架中的fixture机制,详细讲解其核心功能、装饰器用法及五大关键参数(scope, params, autouse, ids, name)。通过yield实现setup/teardown逻辑,结合参数化测试与多fixture依赖,提供完整的代码示例与执行流程分析,帮助开发者高效构建可维护的自动化测试用例。
什么是fixture
在测试流程中,fixture主要承担以下职责:
为测试提供必要的上下文环境,例如环境变量、数据集(dataset)或基础数据。它将数据与测试用例的定义分离,主要用于处理setup和teardown逻辑。pytest支持代码定制,以满足多样化的测试需求,包括定义传入测试的数据集、配置测试前系统的初始状态以及为批量测试提供数据源。
使用装饰器 @pytest.fixture 标记函数,即可将其定义为fixture。一个完整的fixture定义包含以下参数: @pytest.fixture(scope, params, autouse, ids, name)
如何使用fixture
最基础的用法是将fixture作为测试用例函数的参数传入,随后在测试用例内部直接使用该fixture。当pytest执行测试用例时,会检查函数参数,并搜索同名fixture。若找到匹配的fixture,则先执行该fixture并获取其返回值,随后将该返回值作为参数传递给测试用例。
一个简单的fixture使用示例
import pytest
class Fruit():
def __init__(self,name):
self.name=name
self.cubed=False
def cube(self):
self.cubed=True
class FruitSalad():
def __init__(self,*fruit_bowl):
self.fruit=fruit_bowl
self._cube_fruit()
def _cube_fruit(self):
for fruit in self.fruit:
fruit.cube()
@pytest.fixture()
def fruit_bowl():
return [Fruit("apple"),Fruit("banana")]
def test_fruit_salad(fruit_bowl):
fruit_salad=FruitSalad(*fruit_bowl)
assert all(fruit.cubed for fruit in fruit_salad.fruit)如果不使用fixture功能,代码编写方式如下,这将导致无法利用pytest执行测试用例:
class Fruit():
def __init__(self,name):
self.name=name
self.cubed=False
def cube(self):
self.cubed=True
class FruitSalad():
def __init__(self,*fruit_bowl):
self.fruit=fruit_bowl
self._cube_fruit()
def _cube_fruit(self):
for fruit in self.fruit:
fruit.cube()
def fruit_bowl():
return [Fruit("apple"),Fruit("banana")]
def test_fruit_salad(fruit_bowl):
fruit_salad=FruitSalad(*fruit_bowl)
assert all(fruit.cubed for fruit in fruit_salad.fruit)
bowl = fruit_bowl()
test_fruit_salad(fruit_bowl=bowl)使用fixture传递测试数据
fixture非常适合用于存储测试数据,且它可以返回任意类型的数据。
import pytest
@pytest.fixture()
def a_tuple():
return (1,'foo',None,{'bar':23})
def test_a_tuple(a_tuple):
assert a_tuple[3]["bar"]==32a_tuple 作为一个fixture,主要目的是为 test_a_tuple 提供测试数据。执行 test_a_tuple 时,系统首先检查函数参数,发现存在 a_tuple 参数并定位到该fixture。系统先执行 a_tuple 获取数据 (1, 'foo', None, {'bar': 23}),随后将数据传入测试用例 test_a_tuple。在测试用例中,即可直接使用 a_tuple 变量来访问该测试数据。
使用fixture来执行配置和销毁逻辑
fixture的另一个重要功能是结合 yield 关键字来配置测试用例的 setup 和 teardown 逻辑。
import pytest
@pytest.fixture()
def task_db():
print("start to setup....")
yield "a"
print("start to teardown...")
def test_db(task_db):
print(task_db)
print("start to test")运行结果如下:
start to setup.... a start to test start to teardown..
fixture函数会在测试函数之前运行。如果fixture函数包含 yield,系统会在 yield 处暂停,转而执行测试函数。待测试函数执行完毕后,系统回到fixture继续执行 yield 之后的代码。因此,yield 之前的代码可视为配置过程(setup),yield 之后的代码视为清理过程(teardown)。无论测试过程中发生何种情况,yield 之后的代码都会执行。yield 可以返回值,也可以不返回。
fixture可以使用其他的fixture
import pytest
@pytest.fixture()
def first_entry():
return "a"
@pytest.fixture()
def order(first_entry):
return [first_entry]
def test_order(order):
order.append("b")
assert order==["a","b"]同时使用多个fixture
一个测试用例或一个fixture可以同时依赖并使用多个其他fixture。
import pytest
@pytest.fixture()
def first_entry():
return "a"
@pytest.fixture()
def second_entry():
return 2
@pytest.fixture()
def order(first_entry,second_entry):
return [first_entry,second_entry]
@pytest.fixture()
def expect_list():
return ["a",2,3.0]
def test_order(order,expect_list):
order.append(3.0)
assert order==expect_listfixture的参数介绍
scope,指定fixture的作用范围
用于控制fixture执行配置和销毁逻辑的频率。scope参数有四个可选值:function,class,module,session。默认值为function。 - function:函数级别的fixture,每个测试函数仅运行一次。 - class:类级别的fixture,每个测试类仅运行一次。 - module:模块级别的fixture,每个模块仅运行一次。 - session:会话级别的fixture,每次会话仅运行一次。
params,fixture的参数化
params 是一个列表(list),用于传入fixture的参数,这将导致多次调用。通过 request.param 可以获取列表中的每一个值。
import pytest
@pytest.fixture(params=["a","b"])
def order(request):
return request.param
def test_order(order):
all_order="ab"
assert order in all_order运行结果如下:
collected 2 items
test_usefixture7.py::test_order[a] PASSED test_usefixture7.py::test_order[b] PASSED
request 是Python的一个内置fixture,代表fixture的调用状态。它包含一个 param 字段,该字段会被 @pytest.fixture(params=[“a”,“b”]) 中的 params 列表的一个元素填充。如果 params 包含多个值,系统会多次调用 request.param 以多次执行测试用例。
autouse,为常用的fixture添加autouse选项
对于常用的fixture,可以指定 autouse=True,使得作用域内的所有测试函数都自动运行该fixture。
name,为fixture重命名
import pytest
@pytest.fixture(name="lue")
def a_b_c_d_e():
return "a"
def test_order(lue):
assert lue=="a"
import pytest
@pytest.fixture(name="lue")
def a_b_c_d_e():
return "a"
def test_order(lue):
assert lue=="a"PS:
下面来说下pytest中的fixture参数解析以及用法
当我们在使用pytest实现前后置调用时有两种方式
方式一:
采用setup/teardown以及setup_class/teardown_class类似这种方式去实现前后置调用
方式二:
采用pytest中强大的fixture装饰器来实现
本期文章主要采用方式二来解决测试用例前后置调用的问题
首先我们来看下,pytest中的fixture的参数有哪些,分别是scope,params,autouse,ids,name这5个形参,它们各自的作用域以及作用是什么呢?
下面来说下scope:
“”“
scope:
function(默认)
class
module
session
params:
参数化,支持list,tuple,字典列表,字典元组
autouse:
false(默认)
True
ids:
当使用params参数化时,给每一个值设置一个变量名,其实意义不大
name:
表示的是被@pytest.fixture标记的方法取一个别名,注意:当去了别名之后,原来的名称无法使用
”“”
@pytest.fixture(scope='function')
def my_fixture():
print('这是前置内容')
yield
print('这是后置内容')
class Testdemo():
def test01(self,my_fixture):
print('这是test01')
def test02(self):
print('这是test02')根据上面的结构,运行后输出的内容为 这是前置内容 这是test01 这是后置内容 这是前置内容 这是test02 这是后置内容
对于上述方法中传入my_fixture的做法,主要是对比setup/teardown之类的更方便,不需要每个方法都在运行之前执行一遍setup,而是在某个方法需要这种操作时再执行。
到此这篇关于pytest-fixture及其用法的文章就介绍到这了,更多相关pytest fixture用法内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













