pytest-fixture简介及其用法讲解
什么是fixture
在一个测试过程中,fixture主要提供以下功能:
为测试提供上下文,比如环境变量,数据集(dataset),提供数据,数据和测试用例分开定义测试的步骤,主要用于setup和teardown
pytest中的代码可以定制,满足多变的测试需求,包括定义传入测试中的数据集、配置测试前系统的初始状态、为批量测试提供数据源 fixture定义
使用装饰器 @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"]==32
a_tuple作为一个fixture,主要是提供测试数据给test_a_tuple,执行test_a_tuple时,先查看函数的参数,有a_tuple,并且找到了这个函数,先执行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_list
fixture的参数介绍
scope,指定fixture的作用范围
用于控制fixture执行的配置和销毁逻辑的频率
scope参数有四个值:function,class,module,session
默认值为function
function:函数级别的fixture每个测试函数只需要运行一次,
class:类级别的fixture每个测试类只运行一次
module:模块级别的fixture,每个模块只需要运行一次
session:绘画级别的fixture,每次会话只需要运行一次
params,fixture的参化
params是一个list,这个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有多个值,就会多次调用requeat.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用法内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
Django makemigrations migrate执行成功但不创建数据库表的解决
这篇文章主要介绍了Django makemigrations migrate执行成功但不创建数据库表的解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教2023-09-09
最新评论