5、接口测试 - 环境初始化

一、 fixture

1. fixture 详解

fixture(scope='function',params=None,autouse=False,ids=None,name=None)

  • scope:有四个级别参数”function”(默认),”class”,”module”,”session”
  • params:一个可选的参数列表,它将导致多个参数调用fixture功能和所有测试使用它。
  • autouse:如果True,则为所有测试激活fixture func可以看到它。如果为False则显示需要参考来激活fixture
  • ids:每个字符串id的列表,每个字符串对应于params这样他们就是测试ID的一部分。如果没有提供ID它们将从params自动生成
  • name:fixture的名称。这默认为装饰函数的名称。如果fixture在定义它的统一模块中使用,夹具的功能名称将被请求夹具的功能arg遮蔽,解决这个问题的一种方法时将装饰函数命

2. fixture 作用范围

scope 参数可以控制fixture的作用范围:

session > module > class > function

  • function:每一个函数或方法都会调用
  • class:每一个类调用一次,一个类中可以有多个方法
  • module:每一个.py文件调用一次,该文件内又有多个 function 和 class
  • session:是多个文件调用一次,可以跨 .py 文件调用,每个 .py 文件就是 module

3. 调用 fixture 的三种方法

1. 函数或类里面方法直接传 fixture 的函数参数名称

1
2
3
4
5
6
@pytest.fixture()
def test1():
print('\n开始执行function')

def test_a(test1):
print('---用例a执行---')

2. 使用 装饰器 @pytest.mark.usefixtures() 修饰 需要运行的用例

1
2
3
4
5
6
7
8
9
import pytest

@pytest.fixture()
def test1():
print('\n开始执行function')

@pytest.mark.usefixtures('test1')
def test_a():
print('---用例a执行---')

3. 叠加 usefixtures

如果一个方法或者一个 class用例想要勇士调用多个 fixture

可以使用 @pytest.mark.usefixture() 进行叠加

注意叠加顺序:先执行的放底层,后执行的放上层

1
2
3
4
5
6
7
8
9
10
11
12
@pytest.fixture()
def test1():
print('\n开始执行function1')

@pytest.fixture()
def test2():
print('\n开始执行function2')

@pytest.mark.usefixtures('test1')
@pytest.mark.usefixtures('test2')
def test_a():
print('---用例a执行---')

4. usefixtures 和 fixture 区别

装饰器usefixture与用例直接传fixture参数的区别 :如果fixture有返回值,那么 usefixture 无法获取到返回

fixture 需要用到 return 出来的参数时,只能将参数名称直接当参数传入,

不需要用到return出来的参数时,两种方式都可以。

autouse设置为True,自动调用fixture功能

二、fixture 的使用

创建 conftest.py 文件,所有初始化内容写在里边。

1. 直接使用

1
2
3
4
5
6
7
8
9
@pytest.fixture(scope='session', autouse=True)  # 整一个包都会执行,
def start_demo(request): # 这个一个运行该包下,任何一个test文件,都会一开始就执行的操作
print('---开始执行自动化测试---')

# 数据清除操作:删除测试生成的垃圾数据
def fin():
print('---自动化测试---结束')

request.addfinalizer(fin)

2. 手动调用 —- 无 return 传参

1
2
3
4
5
6
# conftest.py

@pytest.fixture(scope='function')
def update_shop_init(): # 更新商铺的环境初始化
# 1- 登录---setup_class---已经在类初始化做了--这边不需要做
print('---我的作用是商铺更新的初始化操作---')
1
2
3
4
5
6
7
8
9
# test_myShop.py

@pytest.mark.usefixtures('update_shop_init') # 使用初始化---不能使用返回值
@pytest.mark.parametrize('inData,respData', get_excelData2('我的商铺', 'updateshopping'))
def test_shop_update(self, inData, respData, update_shop_init): # 列出商铺
res = MyShop(self.token).shop_update(inData, update_shop_init[0], update_shop_init[1]) # 商铺列出方法
# shopId,imageInfo---对应的---update_shop_init[0],update_shop_init[1]
print('update_shop_init:--->', update_shop_init[0], update_shop_init[1])
assert res['code'] == respData['code']

3. 手动调用 —- 有 return 传参

1
2
3
4
5
6
7
8
9
10
11
12
13
# conftest.py

@pytest.fixture(scope='function')
def update_shop_init(): # 更新商铺的环境初始化
# 1- 登录---setup_class---已经在类初始化做了--这边不需要做
print('---我的作用是商铺更新的初始化操作---')
# 1- 登录成功
token = Login().login({"username": "sq0001", "password": "123456"}, getToken=True)
# 2- 列出商铺--id
shopId = MyShop(token).shop_list({'page': 1, 'limit': 20})['data']['records'][0]['id']
# 3-文件上传
imageInfo = MyShop(token).file_upload('123.png', '../data/123.png')
return shopId, imageInfo # 元组类型
1
2
3
4
5
6
7
8
9
# test_myShop.py

# 2- 测试类--接口方法
@pytest.mark.parametrize('inData,respData', get_excelData2('我的商铺', 'updateshopping'))
def test_shop_update(self, inData, respData, update_shop_init): # 列出商铺
res = MyShop(self.token).shop_update(inData, update_shop_init[0], update_shop_init[1]) # 商铺列出方法
# shopId,imageInfo---对应的---update_shop_init[0],update_shop_init[1]
print('update_shop_init:--->', update_shop_init[0], update_shop_init[1])
assert res['code'] == respData['code']