接口自动化框架关于接口关联的封装
一、类之间继承问题:
由于在test_api.py定义了全局变量,而test.user.py想使用这些全局变量就得导入test_api.py模块
但是因为test_user.py导入了test_api.py的模块并使用,到时候执行test_user.py的时候会把test.api.py中的方法(用例)也执行一遍
#演示:
目录结构:

test_api.py
import requests
class TestRequest():
#全局变量,类变量,通过类名调用
access_token=""
sess=requests.session() #定义全局变量sess=requests.session(),将所有的requests都替换为requests.session()就相当于都在一个会话中了
# 获取接口统一鉴权码token
def test_token(self):
url = "http://47.108.153.47:8089/qzcsbj/user/login"
shuju={
"username": "ddance",
"password": "000000"
}
res=TestRequest.sess.request(method="post",url=url,json=shuju) #将所有的requests都替换为requests.session()就相当于都在一个会话中了
print(res.json())
TestRequest.access_token=res.json()["data"]["token"] #将token的值赋给全局变量access_token
#修改一个商品
def test_edit_product(self):
url = "http://47.108.153.47:8089/qzcsbj/product/update"
shuju = {
"product": {
"id": 381,
"price": 20, #将价格改为20元
"productName": "狗粮"
},
"token": TestRequest.access_token
}
res=TestRequest.sess.request(method="post",url=url,json=shuju) #将所有的requests都替换为requests.session()就相当于都在一个会话中了
print(res.json())
#文件上传
def test_file_upload(self):
shuju = {
"name": "01"
}
shuju1={
"uploadfile":open(r"C:\01.jpg","rb"), #r:转义 rb:转化为只读的二进制流
}
url = "http://47.108.153.47:8089/qzcsbj/file/upload?name=" + shuju["name"] #接口文档中规定要将name的值跟在url之后,因此这里使用字典key提取name的值01拼接到url之后
res=TestRequest.sess.request(method="post",url=url,json=shuju,files=shuju1) #上传文件的时候使用files而不是data或者json #将所有的requests都替换为requests.session()就相当于都在一个会话中了
print(res.json())
test_user.py
import requests
from testcases.test_api import TestRequest #导入testcases包下的test_api模块下的TestRequest类
class TestUser():
#修改用户信息
def test_edit_user(self):
shuju={
"token": TestRequest.access_token, #使用TestRequest类的全局变量access_token
"user": {
"id": 1305,
"username": "ddance",
"password": "000000",
"realName": "string",
"sex": "0",
"birthday": "2001-01-01",
"phone": "13542588888", #修改电话号码为13542588888
"utype": "0",
"addtime": "2023-05-12 22:21:56.0",
"adduser": "ddance"
}
}
url = "http://47.108.153.47:8089/qzcsbj/user/update"
res=requests.request(method="post",url=url,json=shuju)
print(res.json())
all.py
import pytest
if __name__ == '__main__':
pytest.main()
执行结果:
D:\JetBrains\PycharmProjects\API接口测试\venv\Scripts\python.exe D:\JetBrains\PycharmProjects\API接口测试\all.py
============================= test session starts =============================
testcases\test_api.py ... [ 42%] #这里3个“.”表示执行了3个用例
testcases\test_user.py .... [100%] #这里4个“.”表示执行了4个用例
============================== 7 passed in 0.93s ==============================
Process finished with exit code 0
为什么test_user.py中明明一个用例却执行了4个用例呢?这是因为test_user.py调用test_api.py下的类的时候把test_api.py类下的用例也执行了一遍
如何避免这种错误呢,可以去掉全局变量,用YAML文件代替保存解决:
#演示:
目录结构:#新增一个ymal空文件extract.yaml,使用yaml_util.py模块将test_api.py产生的全局变量access_token存储到extract.yaml,test_user.py在将extract.yaml中的内容提取使用

yaml_util.py
import yaml #需要安装模块:pip install pyyaml
import os
#读取
def read_yaml(key):
with open(os.getcwd()+'/extract.yaml',mode='r',encoding='utf-8') as f: #os.getcwd()方法用于返回当前工作目录 #mode='a':追加|'w':覆盖|'r':只读 #encoding编码格式
print('这里是打印'+os.getcwd()+'/extract.yaml')
value=yaml.load(stream=f,Loader=yaml.FullLoader) #yaml.load()读取yaml文件 #stream=f要读取的对象 #Loader=yaml.FullLoader全部提取
return value[key] #value是字典类型的,可以通过关键字方式输出值
#写入
def write_yaml(data):
with open(os.getcwd()+'/extract.yaml',mode='a',encoding='utf-8') as f:
yaml.dump(data,stream=f,allow_unicode=True) #yaml.dump()写入数据到yaml文件 #allow_unicode=True允许unicode方式
#清空
def clear_yaml():
with open(os.getcwd()+'/extract.yaml',mode='w',encoding='utf-8') as f:
f.truncate() #清空文件内容
test_api.py #1、删除全局变量access_token 2、修改test_token用例中保存token的方式(存到文件中) 3、修改test_edit_product用例中获取token的方式(从文件中读取)
import requests
from common.yaml_util import read_yaml,write_yaml
class TestRequest():
#全局变量,类变量,通过类名调用
##删除access_token=""
sess=requests.session() #定义全局变量sess=requests.session(),将所有的requests都替换为requests.session()就相当于都在一个会话中了
# 获取接口统一鉴权码token
def test_token(self):
url = "http://47.108.153.47:8089/qzcsbj/user/login"
shuju={
"username": "ddance",
"password": "000000"
}
res=TestRequest.sess.request(method="post",url=url,json=shuju) #将所有的requests都替换为requests.session()就相当于都在一个会话中了
print(res.json())
#删除TestRequest.access_token=res.json()["data"]["token"] #将token的值赋给全局变量access_token
write_yaml({"access_token":res.json()["data"]["token"]}) #将{"access_token":token的值}键值对写入extract.yaml文件
#修改一个商品
def test_edit_product(self):
url = "http://47.108.153.47:8089/qzcsbj/product/update"
shuju = {
"product": {
"id": 381,
"price": 20, #将价格改为20元
"productName": "狗粮"
},
#删除"token": TestRequest.access_token
"token": read_yaml("access_token") #读取extract.yaml文件中key为access_token对应的值
}
res=TestRequest.sess.request(method="post",url=url,json=shuju) #将所有的requests都替换为requests.session()就相当于都在一个会话中了
print(res.json())
#文件上传
def test_file_upload(self):
shuju = {
"name": "01"
}
shuju1={
"uploadfile":open(r"C:\01.jpg","rb"), #r:转义 rb:转化为只读的二进制流
}
url = "http://47.108.153.47:8089/qzcsbj/file/upload?name=" + shuju["name"] #接口文档中规定要将name的值跟在url之后,因此这里使用字典key提取name的值01拼接到url之后
res=TestRequest.sess.request(method="post",url=url,json=shuju,files=shuju1) #上传文件的时候使用files而不是data或者json #将所有的requests都替换为requests.session()就相当于都在一个会话中了
print(res.json())
test_user.py #1、删除导入test_api.py中全局变量的方法 2、修改test_edit_user用例中获取token的方式(从文件中读取)
import requests
#删除from testcases.test_api import TestRequest #导入testcases包下的test_api模块下的TestRequest类
from common.yaml_util import read_yaml,write_yaml
class TestUser():
#修改用户信息
def test_edit_user(self):
shuju={
#删除"token": TestRequest.access_token, #使用TestRequest类的全局变量access_token
"token": read_yaml("access_token"), #读取extract.yaml文件中key为access_token对应的值
"user": {
"id": 1305,
"username": "ddance",
"password": "000000",
"realName": "string",
"sex": "0",
"birthday": "2001-01-01",
"phone": "13542588888", #修改电话号码为13542588888
"utype": "0",
"addtime": "2023-05-12 22:21:56.0",
"adduser": "ddance"
}
}
url = "http://47.108.153.47:8089/qzcsbj/user/update"
res=requests.request(method="post",url=url,json=shuju)
print(res.json())
all.py
import pytest
if __name__ == '__main__':
pytest.main(['-vs'])
执行结果:
D:\JetBrains\PycharmProjects\API接口测试\venv\Scripts\python.exe D:\JetBrains\PycharmProjects\API接口测试\all.py
============================= test session starts =============================
testcases/test_api.py::TestRequest::test_token {'code': 2003, 'msg': '登录成功', 'data': {'token': 'ddance_c08566ea-529b-4817-a8cf-edf20a3da6e8'}}
PASSED
testcases/test_api.py::TestRequest::test_edit_product {'code': 3005, 'msg': '更新商品成功', 'data': {'id': 381, 'productName': '狗粮', 'price': 20.0}}
PASSED
testcases/test_api.py::TestRequest::test_file_upload {'code': 7001, 'msg': '文件上传成功', 'data': '01_01.jpg_4d37c6cc-c3e1-4f46-9fa4-bfd9153a6e34.jpg'}
PASSED
testcases/test_user.py::TestUser::test_edit_user {'code': 2009, 'msg': '更新用户成功', 'data': {'id': 1305, 'username': 'ddance', 'password': '******', 'realName': 'string', 'sex': '0', 'birthday': '2001-01-01', 'phone': '13542588888', 'utype': '0', 'addtime': '2023-05-12 22:21:56.0', 'adduser': 'ddance'}}
PASSED
============================== 4 passed in 0.23s ==============================
Process finished with exit code 0
extract.yaml #生成了一条token的值
access_token: ddance_c08566ea-529b-4817-a8cf-edf20a3da6e8
以上代码仍有问题,由于write.yaml()选择追加的方式写入数据,多次执行后extract.yaml文件中会有多个access_token:[value]键值对,到时候read.yaml()取值的时候可能会报错,解决办法是增加前后置方法在每次写入文件前清空extract.yaml文件
#演示:
目录结构:#增加前后置固件

conftest.py
import pytest
from common.yaml_util import write_yaml,read_yaml,clear_yaml
#在所有接口请求之前执行
@pytest.fixture(scope='package',autouse=True) #作用域是包,即testcases目录,并且自动执行,其余文件无需任何修改
def clear_extract():
clear_yaml() #这是一个前置
如果test_user.py中用例需要test_api.py中用例的cookie怎么办呢?可以调用test_api.py中全局变量sess=requests.session()使两个文件中的用例处于同一个会话(session),但是这样同样会因为类之间继承的问题导致test_api.py被调用时再执行一次,怎么解决呢,可以使用统一请求封装