API测试框架设计---基于Pytest
目录
准备工作
框架目录
base:请求方法
data:存放数据
utils:操作方法
log:日志
report:存放测试报告
tests:测试主程序
common:公共方法
封装请求方法
在base目录下创建requests.py文件 将常用请求方法 封装
import requests
"""请求方法的封装"""
class request:
def request(self,url,method='post',**kwargs):
'''
:param url: 请求地址
:param method: 请求方法
:param kwargs: 请求参数
:return:
'''
if method == 'post':
return requests.request(url=url,method=method,**kwargs)
elif method == 'get':
return request.request(url=url,method='get',**kwargs)
elif method == 'put':
return requests.request(url=url,method='put',**kwargs)
elif method == 'delete':
return request.request(url=url,method='delete',**kwargs)
def post(self,url,**kwargs):
return self.request(url=url,method='post',**kwargs)
def get(self,url,**kwargs):
return self.request(url=url,**kwargs)
def put(self,url,**kwargs):
return self.request(url=url,method='put',**kwargs)
def delete(self,url,**kwargs):
return self.request(url=url,method='delete',**kwargs)
封装查找文件路径公共
在base目录下创建公共方法pubilc.py
import os
def dir_path(filepath='data',filename =None):
"""
:param filepath: 文件路径
:param filename: 文件名称
:return:
"""
return os.path.join(os.path.dirname(os.path.dirname(__file__)),filepath,filename)
对Excel操作方法进行封装
在utils目录下创建方法operationExcel.py文件
import xlrd
from common.pbulc import *
class ValueExcels:
caseID = 0
des = 1
url = 2
method = 3
data = 4
expect = 5
def CaseID(self):
return self.caseID
def description(self):
return self.des
def Url(self):
return self.url
def Method(self):
return self.method
def Data(self):
return self.data
def Expect(self):
return self.expect
class OperationExcel():
# valueExcels = ValueExcels()
def get_excel(self):
'''打开Excel文件'''
db = xlrd.open_workbook(dir_path(filename='data.xls'))
sheet = db.sheet_by_index(0)
return sheet
def get_row(self):
'''获取Excel有多少行内容'''
return self.get_excel().nrows
def getValue(self,row,cel):
return self.get_excel().cell_value(row,cel)
def getCaseID(self,row):
'''获取caseid列'''
return self.getValue(row,ValueExcels().CaseID())
def getURL(self,row):
return self.getValue(row,ValueExcels().Url())
def getdata(self,row):
return self.getValue(row,ValueExcels().Data())
def getmethod(self,row):
return self.getValue(row,ValueExcels().Method())
o = OperationExcel()
# print(o.getValue(1,ValueExcels().Url()))
print(o.getCaseID(1))
print(o.getURL(1))
print(o.getdata(1))
print(o.getmethod(1))
操作yaml文件
在utils目录下创建操作yaml文件的方法
import yaml
from common.pbulc import *
class Operationyaml():
def dictyaml(self,filepath='data',filename='login.yaml'):
with open(dir_path(filepath=filepath,filename=filename),'r',encoding='utf-8') as f:
return yaml.safe_load(f)
o = Operationyaml()
print(o.dictyaml())
>>>{'data_01': {'phone': 11123412312, 'password': 123456}}
获取yaml文件中的请求参数
修改utils文件夹下operationexcel文件 getdata方法取值方法
要获取yaml文件中,如:data_01对应的value参数 要利用excel中data列的值 建立一个映射关系 获取yaml文件中的参数
import xlrd
from common.pbulc import *
from utils.operationyaml import Operationyaml#导入yaml文件
class ValueExcels:
caseID = 0
des = 1
url = 2
method = 3
data = 4
expect = 5
def CaseID(self):
return self.caseID
def description(self):
return self.des
def Url(self):
return self.url
def Method(self):
return self.method
def Data(self):
return self.data
def Expect(self):
return self.expect
class OperationExcel(Operationyaml):#继承Operationyaml类
def get_excel(self):
'''打开Excel文件'''
db = xlrd.open_workbook(dir_path(filename='data.xls'))
sheet = db.sheet_by_index(0)
return sheet
def get_row(self):
'''获取Excel有多少行内容'''
return self.get_excel().nrows
def getValue(self,row,cel):
return self.get_excel().cell_value(row,cel)
def getCaseID(self,row):
'''获取caseid列'''
return self.getValue(row,ValueExcels().CaseID())
def getURL(self,row):
return self.getValue(row,ValueExcels().Url())
def getdata(self,row):
# print(self.getValue(row, ValueExcels().Data()))
#在这里 利用字典取值key:value的方式 将excel中key对应的yaml文件中的参数取到
return self.dictyaml()[self.getValue(row, ValueExcels().Data())]
def getmethod(self,row):
return self.getValue(row,ValueExcels().Method())
o = OperationExcel()
print(o.getdata(2))
>>>{"page":1}
测试主方法
tests目录下创建test_API.py文件
把请求方法 操作文件的方法 全部导入 发送API请求
from base.mthod import request
from utils.operationExcel import OperationExcel
from utils.operationyaml import Operationyaml
import pytest
import json
class TestRun:
excel = OperationExcel()
obj = request()
def test_YLMY_login(self):
"""登录"""
r = self.obj.post(
url=self.excel.getURL(1),
data=self.excel.getdata(1)
)
print(r.json())
if __name__ == '__main__':
pytest.main('-v','test_API.py')
token的处理
在登录请求获取写入文件
pubilc路径下写一个 写入方法,写入文件的目录在默认的data路径下 一会儿在登录接口调用这个方法 将token写入txt文件
def writetoken(contest):
"""
:param contest: 写入内容的形参
:return:
"""
with open(dir_path(filename='token.txt'),'w') as f:
f.write(contest)
登录接口调用文件写入方法
from common.pbulc import *
def test_YLMY_login(self):
"""登录"""
r = self.obj.post(
url=self.url() + self.excel.getURL(1),
data=self.excel.getdata(1)
)
writetoken(json.dumps({"token":r.json()['data']['token']}))
查找token.txt文件路径
在utils目录下创建readlinetoken.py文件
from common.pbulc import *
def dir_token():
db = dir_path("data",'token.txt')
return db
def get_token():
file =open(dir_token(),'r')
token = file.readline()
file.close()
return token
在其他接口请求中使用token
from base.mthod import request
from utils.operationExcel import OperationExcel
from utils.operationyaml import Operationyaml
from utils.readlinetoken import get_token #导入查找token文件路径方法
import pytest
import json
class TestRun:
excel = OperationExcel()
obj = request()
def test_YLMY_login(self):
"""登录"""
r = self.obj.post(
url=self.excel.getURL(1),
data=self.excel.getdata(1)
)
print(r.json())
writetoken(json.dumps({"token":r.json()['data']['token']}))
def test_YLMY_info(self):
"""我的"""
r = self.obj.post(
url=self.excel.getURL(2),
headers=json.loads(get_token()) #拼接headers
)
print(json.dumps(r.json(),indent=True,ensure_ascii=False))
if __name__ == '__main__':
pytest.main('-v','test_API.py')
断言
在Excel表期望结果列中写入结果与返回数据进行对比
在excel表中第一行预期结果中写入msg对应的登录成功 然后写断言
def test_YLMY_login(self):
"""登录"""
r = self.obj.post(
url=self.url() + self.excel.getURL(1),
data=self.excel.getdata(1)
)
assert self.excel.getexpect(row=1) in json.dumps(r.json(),ensure_ascii=False)
writetoken(json.dumps({"token":r.json()['data']['token']}))
这个断言在每个接口中都会使用 所以封装成一个方法 方便调用
def result(self,r,row):
"""
:param r: 实际结果
:param row:预期结果所在行
:return:断言方法
"""
assert r.status_code == 200
assert self.excel.getexpect(row=row) in json.dumps(r.json(),ensure_ascii=False)
def test_YLMY_login(self):
"""登录"""
r = self.obj.post(
url=self.url() + self.excel.getURL(1),
data=self.excel.getdata(1)
)
# assert self.excel.getexpect(row=1) in json.dumps(r.json(),ensure_ascii=False)
self.result(r=r,row=1)#调用result断言方法
writetoken(json.dumps({"token":r.json()['data']['token']}))
URL路径分离
测试环境和生产环境只是域名 不同 后面的路径都是相同的所以 在测试后测试环境后 在线上环境测试还要改域名 太麻烦 现在把excel表里的域名 分离出来 放到一个公共方法里 这样在测试和正式环境 切换时 就只需要改一个就可以了
在操作operationexcel.py 文件中的geturl方法中 修改url获取方法 把前面的域名和excel表中的路径拼接起来
def getURL(self,row):
url = "http://127.0.0.1:5000" + self.getValue(row,ValueExcels().Url())
return url
# return self.getValue(row,ValueExcels().Url())
主方法不用改变 直接请求 这样切换测试环境时 只需要改一次就可以了
def test_YLMY_login(self):
"""登录"""
r = self.obj.post(
url=self.excel.getURL(1),
data=self.excel.getdata(1)
)
# assert self.excel.getexpect(row=1) in json.dumps(r.json(),ensure_ascii=False)
self.result(r=r,row=1)
writetoken(json.dumps({"token":r.json()['data']['token']}))
请求参数化
一个页面的接口有很多个page页 要测试 又不可能封装好几个用例 这样可以将page重构成动态的
用更改字典k值的方式 将参数构造成动态的
from utils.operationExcel import OperationExcel
excel= OperationExcel()
def getpage(page):
dict1= excel.getdata(3)
dict1['page']=page
return dict1
导入上面的操作函数 在data参数上调用 然后传入什么参数就是什么参数了
def test_YLMY_index(self):
"""首页"""
r =self.obj.post(
url=self.excel.getURL(3),
data = getpage(2)
)
print(p)
print(r.status_code)
我想一次测试完page1到page5可以把参数放到列表里 然后for循环传入即可
ef test_YLMY_index(self):
"""首页"""
page = [1,2,3,4,5]
for p in page:
r =self.obj.post(
url=self.excel.getURL(3),
data = getpage(p)
)
print(p)
print(r.status_code)
测试报告
Allure生成HTNL测试报告
配置工作:
1、下载地址:http://allure.qatools.ru/
2、下载完成解压后将bin目录的路径添加到path环境变量中
3、DOS命令输入 allure验证是否完成 如果没有报错 说明没问题
4、输入 pip install allure-pytest 安装这个库
生成在线测试报告
执行测试 并使用Allure侦听器在测试执行期间收集结果 --alluredir 提供存储结果的路径
pytest -v test_API.py --alluredir=/report
打开测试报告
allure serve /report
测试报告打开效果
同一个网段下的设备输入本机ip端口号也能访问