一、fixture机制
通俗的讲:fixture=前置+后置
主要目的是可以让我们自定义测试用例的前置条件。
1、conftest文件
设置conftest.py文件,放所有的前置和后置函数,通过设置fixture的作用域,可实现数据共享;
2、把函数声明为fixture
在函数前面加上 @pytest.fixture(作用级别=默认为function),表明这是一个预置函数,方便用户调用;
3、fixture定义
如果有返回值,那么写在yield后面。(yield的作用相当于return)
yield关键字之前的代码,是环境准备;之后的代码,就是环境清理的代码,即在测试用例执行完成之后会执行的代码。
#conftest.py文件
import pytest
@pytest.fixture(scope="function",autouse=True)
def description():
print("这是一个conftest文件")
@pytest.fixture(scope="function",autouse=False)
def get_code():
code="200"
return code
@pytest.fixture(scope="session",autouse=True)
def get_token():
token="qeehfjejwjwjej11sss@22";
print("获取到token:%s"%token)
return token
二、fixture 参数列表
@pytest.fixture(scope="function",params=None,autouse=False,ids=None,name=None) def test(): print("fixture初始化的参数列表")
1、scope
- 用于控制Fixture的作用范围
- 作用类似于Pytest的setup、teardown
- 默认取值未function(函数级别),控制范围的排序为:session>module>class>function
取值 | 范围 | 说明 |
function | 函数级 | 每一个函数或方法都会调用(默认值) |
class | 类级别 | 每个测试类只运行一次 |
module | 模块机 | 每一个.py文件调用一次 |
session | 会话级 | 每次会话只需要运行一次,多个.py跨文件使用一个session来完成多个用例。 整个测试会话,即开始执行pytest到结束测试; |
2、params
可选的参数列表,它将导致多个参数调用 fixture 功能和所有测试使用它。
3、ids--每个字符串id的列表,
- 用例标识ID
- 与params 配合使用,一对一关系
4、autouse
- 默认false;
- 若为True,刚每个测试函数都会自动调用该fixture,无需传入fixture函数名
5、Name
- fixture的重命名
- 使用fixture的测试函数会将fixture的函数名作为参数传递,但是pytest也允许将fixture重命名;
- 如果使用了name,那只能将name传,函数名不再生效;
- 调用方法:@pytest.mark.usefixture('fixture1','fixture2');
三、通过conftest.py 共享fixture
1、共享fixture
fixture 可以放在单独的测试文件里。如果你希望多个测试文件共享fixture,可以在某个公共目录下新建一个conftest.py 文件,将fixture 放在其中,这样该项目中的所有测试都能共享其中的fixture。
如果你希望 fixture 的作用域仅限于某个测试文件,那么将它写在该测试文件里,也可以在tests目录的子目录下创建新的conftest.py文件,低一级的conftest.py 中的fixture可以供所在目录及其子目录下的测试使用。
四、调用fixture的三种方法
1、函数或类里面方法直接传 fixture 的函数参数名称
2、使用装饰器 @pytest.mark.usefixture(fixture_name) 装饰需要运行的用例;
叠加 usefixture,如果一个方法或者一个class用例想要同时调用多个fixture,可以使用@pytest.mark.usefixture() 进行叠加,注意叠加顺序,先执行的放底层,后执行的放上层。
3、根据fixture的作用域及autouse参数,确定调用fixture的方式。
例如:当fixture的参数autouse为True时,每次执行方法前都会调用方法;
4、示例:
import pytest
# 调用方式一:传fixture的函数参数名称
@pytest.fixture
def login():
print("输入账号,密码先登录")
def test_s1(login):
print("用例 1:登录之后其它动作 111")
def test_s2(): # 不传 login
print("用例 2:不需要登录,操作 222")
# 调用方式二:使用装饰器
@pytest.fixture
def login2():
print("please输入账号,密码先登录")
@pytest.mark.usefixtures("login2")
def test_s11():
print("用例 11:登录之后其它动作 111")
# 调用方式三:autouse=True
@pytest.fixture(autouse=True)
def login3():
print("====auto===")
# 不是test开头,加了装饰器也不会执行fixture
@pytest.mark.usefixtures("login2")
def loginss():
print(123)
5、注意
- 在类声明上面加@pytest.mark.usefixtures(),代表这个类里面所有测试用例都会调用该fixture;
- 可以叠加多个@pytest.mark.usefixtures(),先执行的放底层,后执行的放上层
- 可以传多个fixture参数,先执行的放前面,后执行的放后面
- 如果fixture有返回值,用@pytest.mark.usefixtures() 是无法获取到返回值的,必须用传参的方式(方式一)
五、fixture的实例化顺序
1、较高scope范围的fixture(session)在较低scope范围的fixture(function、class)之前实例化【session>package>module>class>function】
2、具有相同作用域的fixture遵循测试函数中声明的顺序,并遵循fixture之间的依赖关系。
3、自动使用(autouse=True)的fixture将在显式使用(传参或装饰器)的fixture之前实例化。
六、关于fixture的注意点
1、添加了@pytest.fixture,如果fixture还想依赖其他fixture,需要用函数传参的方式,不能用@pytest.mark.usefixtures() 的方式,否则会不生效。
六、示例
1、返回数值的简单fixture
import pytest
@pytest.fixture()
def some_data():
return 42
def test_some_data(some_data):
assert some_data==42
if __name__ == '__main__':
pytest.main()
2、说明
@pytest.fixture() 装饰器用于声明函数是一个 fixture。如果测试函数列表中包含fixture名,那么pytest会检测到,并在测试函数运行之前执行该fixture。fixture可以完成任务,也可以返回数据给测试函数。