一、解决接口关联的三种方式
接口关联:接口2的入参需要接口1的返回值
(1).将关联值保存在类变量中(不能跨文件使用)
(2).将关联值保存在extract.yaml文件中。接口1写入关联值,接口2读取关联值
(3).封装请求类,测试用例数据中写{{access_token}},封装的请求类在实际发送请求时,会将{{access_token}}替换为extract.yaml的真实值
二、接口关联---将关联值保存在extract.yaml文件
接口1:上传图片,返回图片的URL
接口2:将图片上传至相册,需要接口1的图片URL
1、创建extract.yaml文件保存关联值
2、编写工具类读写extract.yaml中的值
python
def read_extract_yaml(self,key):
path="C:\\Users\\mingyuewu\\PycharmProjects\\mashang\\config\\extract.yaml"
with open(path,mode="r",encoding="utf-8") as f:
value = yaml.load(stream=f,Loader=FullLoader)
#读取的value为字典格式
return value[key]
def write_extract_yaml(self,data):
path="C:\\Users\\mingyuewu\\PycharmProjects\\mashang\\config\\extract.yaml"
# data需为字典格式
with open(path,mode="a+",encoding="utf-8") as f:
yaml.dump(data,stream=f,allow_unicode=True)
# 清空文件
def clear_extract_yaml(self):
path = "C:\\Users\\mingyuewu\\PycharmProjects\\mashang\\config\\extract.yaml"
with open(path, mode="w", encoding="utf-8") as f:
f.truncate()
3、接口上传图片、图片上传相册
python
def test_login(self):
url= "/api/login"
data ={
"username": "username",
"password": "password"
}
res= RequestUtil().send_request("post", url=url, data=data)
def test_upload_photo(self):
# ConfigYamlUtil().clear_extract_yaml()
url="/api/admin/photos/albums/cover"
method = "post"
files = {
"file": ("1.webp", open("./1.webp", "rb"), "application/octet-stream")
}
res = RequestUtil().send_request(method=method, url=url, files=files)
cover_url = jsonpath.jsonpath(res.json(), '$.data')[0]
data = {"cover_url": cover_url}
# 将关联值写入文件
ConfigYamlUtil().write_extract_yaml(data)
def test_upload_ablums(self):
url="/api/admin/photos"
method="post"
headers = {
"Content-Type ": "application/json;charset=UTF-8"
}
#从文件读取关联值
cover_url=ConfigYamlUtil().read_extract_yaml("cover_url")
data = json.dumps(
{
"albumId": "1",
"photoUrlList": [cover_url]
}
)
res = RequestUtil().send_request(method=method, url=url, headers=headers, data=data)
print(res.request.body)
print(res.request.headers)
三、封装requestUtil类解析测试数据中的关联值
1、原理
使用extract.yaml处理接口关联时,是在用例方法 中,写入/读取extract.yaml的关联值。
封装requestUtil处理接口关联时,是在requestUtil中添加方法,可以识别测试用例中的关联值。举例:上传图片到相册接口的测试数据photo_testdata.yaml文件如下:
(1)关联值cover_url用{{}}括起来,表示需要解析提取的值。
(2)requestUtil执行send_request方法时,使用参数化读取photo_testdata.yaml中的测试数据。
(3)requestUtil识别测试数据中是否有{{}}标识的变量,如果有则在extract.yaml文件种查找该变量对应的value,将{{}}标识的变量,替换为value
bash
data:
albumId: 5
photoUrlList:
-{{cover_url}}
2、代码
(1)、编写图片上传置接口测试数据upload_photo_album.yaml
yaml
-
feature: 相册管理
story: 上传接口
title: 上传图片到相册
request:
method: post
url: /api/admin/photos
headers:
Content-Type: application/json;charset=UTF-8
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36
Referer: http://114.55.135.15:81/albums/5
data:
albumId: 5
photoUrlList:
- "{{cover_url}}"
validate: success
(2)编写读取测试数据的文件
python
import yaml
class ReadTestdataYaml:
def read_testdata(self,file_path):
#file_path="C:\\Users\\mingyuewu\\PycharmProjects\\mashang\\testdatas\\upload_photo_ablum.yaml"
with open(file_path,mode="r",encoding="utf-8") as f:
value = yaml.load(f,Loader=yaml.FullLoader)
return value
if __name__ =="__main__":
file_path = "C:\\Users\\mingyuewu\\PycharmProjects\\mashang\\testdatas\\upload_photo_ablum.yaml"
print(ReadTestdataYaml().read_testdata(file_path))
(3)封装RequestUtil
deal_variables方法将测试数据种{{}}标识的关联值解析为实际值
send_request种处理了url、headers、params、data、json几种传参方式值的替换
python
import requests
import json
from tools.config_yaml_util import ConfigYamlUtil
class RequestUtil():
# 统一会话
session = requests.session()
# 获取被测系统的IP地址
base=""
# 从配置文件中读取对应IP
def __init__(self):
RequestUtil.base = ConfigYamlUtil().read_config_yaml("url","blog_url")
def deal_variables(self,data):
'''
:param 待处理含{{access_token}}的数据:
:return: 返回将{{}}中的值处理为 extract.yaml文件中对应的实际值
'''
#1、将数据类型全部处理为string,保存在str变量中
if data and isinstance(data,dict):
str = json.dumps(data)
else:
str = data
# url = "http://11.11.11.11:80/index?access_token={{access_token}}&cover_url={{cover_url}}"
# 2、将{{variable}}中的数据替换为extract.yaml中的实际值
for i in range(1, str.count("{{") + 1): #处理字符串中含多个{{}}的情况
if "{{" in str and "}}" in str:
start_index = str.index("{{")
end_index = str.index("}}")
before_var =str[start_index:end_index + 2]
print("\n-------------------替换前{}".format(before_var))
after_var = ConfigYamlUtil().read_extract_yaml(key=before_var[2:-2])
print("-------------------替换后{}".format(after_var))
str = str.replace(before_var, after_var)
print("-------------------最终结果{}".format(str))
# 3、数据类型还原
if data and isinstance(data,dict):
data = json.loads(str)
else:
data = str
return(data)
def send_request(self,method,url,**kwargs):
#1、将method处理为小写
self.method = str(method).lower()
#2、处理URL 拼接完整
self.url= RequestUtil.base+url
#3、将url中类似{{access_token}}的变量,替换为extract.yaml文件中实际的值
self.url = self.deal_variables(self.url)
#4、将headers,params,json,data参数中,类似{{access_token}}的变量,替换为extract.yaml文件中实际的值
for key,value in kwargs.items(): # data ={"username":"{{}}","password"} headers={}
if key in ["headers","params","data","json"]:
kwargs[key] = self.deal_variables(value) #kwargs[key]
#5、发送请求
res=RequestUtil.session.request(method=self.method,url=self.url, **kwargs)
print(res.text)
return res
4、测试用例类
python
@pytest.mark.parametrize('casedata',ReadTestdataYaml().read_testdata("C:\\Users\\mingyuewu\\PycharmProjects\\mashang\\testdatas\\upload_photo_ablum.yaml"))
def test_upload_ablums(self,casedata):
url=casedata["request"]["url"]
method=casedata["request"]["method"]
headers = casedata["request"]["headers"]
#cover_url=ConfigYamlUtil().read_extract_yaml("cover_url")
data=casedata["request"]["data"]
res = RequestUtil().send_request(method=method, url=url, headers=headers, data=json.dumps(data))
print(res.request.body)
print(res.request.headers)