使用requests库封装接口请求
详细教程请查看官方文档:https://requests.kennethreitz.org//zh_CN/latest/user/quickstart.html#url
入门教程:https://www.cnblogs.com/huaerye/p/9132607.html
参考文档:https://www.cnblogs.com/shapeL/p/9045439.html
第一次修改:将get请求和post请求单独定义,使用过程中根据不同类型的请求直接调用对应的方法;
def send_get(url,data,headers):
res = requests.get(url=url,json=data,headers=headers).json()
# return json.dumps(res,sort_keys=True,indent=2)
return res
def send_post(url,data,headers):
res = requests.post(url=url,json=data,headers=headers).json()
return json.dumps(res,sort_keys=True,indent=4) #indent默认情况下为空,4个空格,sort_keys:按照一定顺序展示数据
def run_main(url,headers,method,data=None):
res =None
if method == 'GET':
res = send_get(url,data,headers)
else:
res = send_post(url,data,headers)
return res
if __name__=='__main__':
url = 'https://oapi.blingabc.com/cms/user-api/student/homework/v2/homeworklist'
headers = {
'token': "eyJhbGciOiJIUzUxMiJ9.eyJpc3MiOiJjb20ueGRmLmJsaW5nIiwiYXVkIjoiY2xpZW50IiwidXNlcmNvZGUiOiI5NTUxNjMxNyIsImV4cCI6MTU3NDMxNzY2NSwiaWF0IjoxNTczNzEyODY1fQ.UjNSQSQpP6umRubppSggYB1W-dkmnfBB5RMNRQUTS9a8IJDmURyPT1bMIWg5nwHL1z7GvvJ-Ch5PKGLEnwOh6g",
'Content-Type': "application/json",
}
# 数据
data = {"stuNum":"795571161","page":1,"size": 5,"type":0}
#url = 'https://oapi.t.blingabc.com/bms/admin-api/specialsubject/v1/save-phonics?id=285'
print(send_post(url,data,headers))
第二次修改:用class进行封装,主函数中创建一个实例run来调用类中的方法
import requests
import json
class Runmain():
def send_get(self,url,data,headers):
res = requests.get(url=url,json=data,headers=headers).json()
# return json.dumps(res,sort_keys=True,indent=2)
return res
def send_post(self,url,data,headers):
res = requests.post(url=url,json=data,headers=headers).json()
return json.dumps(res,sort_keys=True,indent=4) #indent默认情况下为空,4个空格,sort_keys:按照一定顺序展示数据
def run_main(self,url,headers,method,data=None):
res =None
if method == 'GET':
res = self.send_get(url,data,headers)
else:
res = self.send_post(url,data,headers)
return res
if __name__=='__main__':
run = Runmain
url = 'https://oapi.blingabc.com/cms/user-api/student/homework/v2/homeworklist'
headers = {
'token': "eyJhbGciOiJIUzUxMiJ9.eyJpc3MiOiJjb20ueGRmLmJsaW5nIiwiYXVkIjoiY2xpZW50IiwidXNlcmNvZGUiOiI5NTUxNjMxNyIsImV4cCI6MTU3NDMxNzY2NSwiaWF0IjoxNTczNzEyODY1fQ.UjNSQSQpP6umRubppSggYB1W-dkmnfBB5RMNRQUTS9a8IJDmURyPT1bMIWg5nwHL1z7GvvJ-Ch5PKGLEnwOh6g",
'Content-Type': "application/json",
}
# 数据
data = {"stuNum":"795571161","page":1,"size": 5,"type":0}
#url = 'https://oapi.t.blingabc.com/bms/admin-api/specialsubject/v1/save-phonics?id=285'
print(run.run_main(url,data,headers))
第三次修改:第二次修改,每次都需要实例化后再调用对应的方法;
改进办法:使用__init__方法实现:只要实例化类时候就会调用__init__方法
import requests
import json
class Runmain():
def __init__(self,url,headers,method,data=None):
self.res = self.run_main(url,headers,method,data)
def send_get(self,url,data,headers):
res = requests.get(url=url,json=data,headers=headers).json()
# return json.dumps(res,sort_keys=True,indent=2)
return res
def send_post(self,url,data,headers):
res = requests.post(url=url,json=data,headers=headers).json()
return json.dumps(res,sort_keys=True,indent=4) #indent默认情况下为空,4个空格,sort_keys:按照一定顺序展示数据
def run_main(self,url,headers,method,data=None):
res =None
if method == 'GET':
res = self.send_get(url,data,headers)
else:
res = self.send_post(url,data,headers)
return res
if __name__=='__main__':
url = 'https://oapi.blingabc.com/cms/user-api/student/homework/v2/homeworklist'
headers = {
'token': "eyJhbGciOiJIUzUxMiJ9.eyJpc3MiOiJjb20ueGRmLmJsaW5nIiwiYXVkIjoiY2xpZW50IiwidXNlcmNvZGUiOiI5NTUxNjMxNyIsImV4cCI6MTU3NDMxNzY2NSwiaWF0IjoxNTczNzEyODY1fQ.UjNSQSQpP6umRubppSggYB1W-dkmnfBB5RMNRQUTS9a8IJDmURyPT1bMIWg5nwHL1z7GvvJ-Ch5PKGLEnwOh6g",
'Content-Type': "application/json",
}
# 数据
data = {"stuNum":"795571161","page":1,"size": 5,"type":0}
#url = 'https://oapi.t.blingabc.com/bms/admin-api/specialsubject/v1/save-phonics?id=285'
run = Runmain(url,headers,data,'post')
print(run.res)
最后修改后的文件:将形参写到构造方法中,params=None,data=None,需要时可以传入参数;
demo.py使用requests get以及post方法进行了封装,主要是根据传递的参数method来对get以及post方法进行分别调用
import requests
import json
class Runmain():
def __init__(self,url,headers,method,params=None,data=None):
self._url=url
self._params = params
self._data = data
self._headers = headers
self._method = method
def send_get(self,url,params,headers):
res = requests.get(url=url,params=params,headers=headers).json()
#return json.dumps(res,sort_keys=True,indent=2)
return res
def send_post(self,url,data,headers):
res = requests.post(url=url,json=data,headers=headers).json()
return json.dumps(res,sort_keys=True,indent=4)
def run_main(self):
if self._method == 'GET':
return self.send_get(self._url,self._params,self._headers)
else:
return self.send_post(self._url,self._data,self._headers)
if __name__=='__main__':
url = 'https://oapi.t.blingabc.com/bms/admin-api/studentPreview/v1/myPreviews'
headers = {
'token': "eyJhbGciOiJIUzUxMiJ9.eyJpc3MiOiJjb20ueGRmLmJsaW5nIiwiYXVkIjoiY2xpZW50IiwidXNlcmNvZGUiOiI5NTUxNjMxNyIsImV4cCI6MTU3NDMzMDY5NiwiaWF0IjoxNTczNzI1ODk2fQ.yWaCaeOzZfVGokA7D7wrGeItcKPeyuythWIU52_1-rqZ9vEpYWRl6EYmq5thebccD0SecVpu6qLZm3NZu9DIqQ",
'Content-Type': "application/json",
#'user-agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36"
}
# 数据
data = {"stuNum":"955163171","page":1,"size":5,"type":2}
# url = 'https://oapi.t.blingabc.com/bms/admin-api/specialsubject/v1/save-phonics?id=285'
run = Runmain(url,headers,'post',data).run_main()
print(run)
unittest测试框架使用
详细用法请参考:https://www.cnblogs.com/huaerye/p/9361892.html
在test_method.py文件中则创建测试类以及test方法,在test方法中调用demo.py中的run_main方法,即使用requests模块向传递的接口url地址和请求方式以及请求体发送对应的请求,这里使用setUp方法则是利用其优先调用而对RunMain类进行实例化
import unittest
from demo import Runmain
class TestMethod(unittest.TestCase):
def test_01(self):
url = 'https://oapi.t.blingabc.com/bms/admin-api/specialsubject/v1/save-phonics?id=285'
headers = {
'token': "eyJhbGciOiJIUzUxMiJ9.eyJpc3MiOiJjb20ueGRmLmJsaW5nIiwiYXVkIjoiY2xpZW50IiwidXNlcmNvZGUiOiI5NTUxNjMxNyIsImV4cCI6MTU3NDMxNzY2NSwiaWF0IjoxNTczNzEyODY1fQ.UjNSQSQpP6umRubppSggYB1W-dkmnfBB5RMNRQUTS9a8IJDmURyPT1bMIWg5nwHL1z7GvvJ-Ch5PKGLEnwOh6g",
'Content-Type': "application/json",
}
res1 = Runmain(url,headers,'GET').run_main()
self.assertEqual(res1['code'],10000,"测试通过") #添加断言
print(res1)
def test_02(self):
url = 'https://oapi.blingabc.com/cms/user-api/student/homework/v2/homeworklist'
headers = {
'token': "eyJhbGciOiJIUzUxMiJ9.eyJpc3MiOiJjb20ueGRmLmJsaW5nIiwiYXVkIjoiY2xpZW50IiwidXNlcmNvZGUiOiI5NTUxNjMxNyIsImV4cCI6MTU3NDMxNzY2NSwiaWF0IjoxNTczNzEyODY1fQ.UjNSQSQpP6umRubppSggYB1W-dkmnfBB5RMNRQUTS9a8IJDmURyPT1bMIWg5nwHL1z7GvvJ-Ch5PKGLEnwOh6g",
'Content-Type': "application/json",
}
data = {"stuNum":"795571161","page":1,"size": 5,"type":0}
res2 = Runmain(url,headers,'post',data).run_main()
self.assertEqual(res2['code'],10000,"测试通过")
print(res2)
if __name__=='__main__':
unittest.main()
#3、还可以将要测试的case添加到unittest.TestSuite集合中执行想要执行的case,若想要全部都执行则需要一个一个的添加
# suite = unittest.TestSuite()
# suite.addTest(TestMethod("test_01"))
数据依赖
设计一个接口自动化测试框架
根据接口地址丶接口类型丶请求数据丶预期结果来进行设计,对于需要登录后才能进行操作的接口那么则需要进行header cookie等数据的传递,自动化测试的难点就是数据依赖。
python操作excel获得内容
python操作excel,需要安装两个包,分别是xlrd和xlwt这两个库,xlrd这个库是负责读取excel数据的,而xlwt库是负责向excel写入数据的;
安装方式:pip3 install xlrd
项目目录下创建utils工具包,在该包下创建operation_excel.py文件,在该文件中通过导入xlrd包,对excel表的数据进行读取操作


重构操作excel函数
根据上一步骤读取excel表的内容代码后,进行了一个简单的封装,提高代码的通用性,实现代码如下:
import xlrd
data = xlrd.open_workbook('../case/interface.xls')
tables = data.sheets()[0] #获取表格数据对象
print(tables.nrows) #打印表格行数
print(tables.cell_value(1,2)) #打印excel表格数据,需要传递所在坐标(x,y)
print("*"*50+"封装前后数据对比"+"*"*50)
class OperationExcel():
def __init__(self,file_name=None,sheet_id=None):
if file_name:
self.file_name = file_name
self.sheet_id = sheet_id
else:
self.file_name='../case/interface.xls'
self.sheet_id = 0
self.data = self.get_data()
#获取sheets的内容
def get_data(self):
data = xlrd.open_workbook(self.file_name)
tables = data.sheets()[self.sheet_id]
return tables
#获取单元格的行数
def get_lines(self):
tables = self.data
return tables.nrows
#获取某一个单元格的内容
def get_cell_value(self,row,col):
tables = self.data
cell = tables.cell_value(row,col)
return cell
if __name__=='__main__':
opers = OperationExcel()
print(opers.get_data().nrows)
print(opers.get_lines())
print(opers.get_cell_value(1,2))
结果对比:

学习操作json文件
如果把请求数据全部放到excel里面,数据量大时,看起来不是很美观,所以将请求数据单独弄成一个json文件,将入参名传入excel就可以了;
在项目下新建一个dataconfig文件用于存json文件,在该文件下创建student.json,文件内容如下:


在utils工具包下创建operation_json.py文件,在文件中对login.json文件内容进行读取操作,以及重构json代码:
import json
fp = open('../dataconfig/student.json')
res = json.load(fp) #加载某个文件
print(res)
print(res['student_login'])
print(res['student_login']['mobile'])
print("="*50+"封装前后数据对比"+"="*50)
class OperationJson():
def __init__(self, file_path="../dataconfig/student.json"):
self.file_path = file_path
self.data = self.get_data()
def get_data(self):
with open(self.file_path) as f:
data = json.load(f)
return data
def get_key_words(self,key=None):
if key:
return self.data[key]
else:
return self.data
if __name__=='__main__':
opjson = OperationJson()
print(opjson.get_key_words())
print(opjson.get_key_words('student_login'))
print(opjson.get_key_words('student_login')['mobile'])
数据结果对比如下图:

封装获取常量方法
首先打开excel表格,查看需要获取的字段有哪些

对excel表的字段进行获取,在项目目录下创建名为data的python包,在该包下创建data_conf.py,代码就是简单的获取对应的变量值,具体如下
class global_var():
id = '0' # id
description = '1' # 接口描述
url = '2' # 接口地址
run = '3' # 是否运行
request_way = '4' # 请求方式
request_header = '5' #是否携带header
case_depend = '6' # case依赖
response_data_depend = '7' # 依赖的返回数据
data_depend = '8' # 数据依赖
request_data = '9' # 请求数据
expect_result = '10' # 预期结果
reality_result = '11' # 实际结果
def get_id():
return global_var.id
def get_description():
return global_var.description
def get_url():
return global_var.url
def get_run():
return global_var.run
def get_request_way():
return global_var.request_way
def get_request_header():
return global_var.request_header
def get_case_depend():
return global_var.case_depend
def get_response_data_depend():
return global_var.response_data_depend
def get_data_depend():
return global_var.data_depend
def get_request_data():
return global_var.request_data
def get_expect_result():
return global_var.expect_result
def get_reality_result():
return global_var.reality_result
封装获取接口数据
在data目录下创建get_data.py文件,在该文件中对excel表数据以及json数据结合上一步封装的常量方法整合后的实现,代码如下
from util.operation_excel import OperationExcel
from util.operation_json import OperationJson
from data import data_config
class GetData():
def __init__(self):
self.op_excel = OperationExcel()
def get_case_lines(self):
"""获取表格行数"""
return self.op_excel.get_lines()
def get_is_run(self,row):
"""获取case是否运行"""
flag = None
col = int(data_config.get_run())
run_model = self.op_excel.get_cell_value(row.col)
if run_model == 'yes':
flag = True
else:
flag = False
return flag
def get_is_header(self,row):
"""是否携带header"""
col = data_config.get_request_header()
header = self.op_excel.get_cell_value(row,col)
if header != 'yes':
return data_config.get_request_header()
else:
return None
def get_request_method(self,row):
"""获取请求方式"""
col = data_config.get_request_way()
request_method = self.op_excel.get_cell_value(row,col)
return request_method
def get_request_url(self,row):
"""获取url地址"""
col = data_config.get_url()
url = self.op_excel.get_cell_value(row,col)
return url
def get_request_data(self,row):
"""获取请求数据"""
col = data_config.get_url()
request_data = self.op_excel.get_cell_value(row,col)
if request_data == '':
return None
return request_data
def get_header_value(self, row):
"""通过excel中的关键字去获取json数据"""
op_json = OperationJson()
data = op_json.get_key_words(self.get_request_data(row))
return data
def get_expect_data(self,row):
"""获取预期结果数据"""
col = data_config.get_expect_result()
expect_data = self.op_excel.get_cell_value(row,col)
if expect_data == '':
return True
return expect_data
post、get基类的封装
在util文件下新创建了run_method.py文件,将开始的demo文件复制了过来,其他未作改动,headers默认参数设置为了None,用时可传入headers参数;
import requests
import json
class Runmain():
def __init__(self,url,method,headers=None,params=None,data=None):
self._url = url
self._params = params
self._data = data
self._headers = headers
self._method = method
def send_get(self,url,params,headers):
res = requests.get(url=url,params=params,headers=headers).json()
#return json.dumps(res,sort_keys=True,indent=2)
return res
def send_post(self,url,data,headers):
res = requests.post(url=url,json=data,headers=headers).json()
return json.dumps(res,sort_keys=True,indent=4)
def run_main(self):
if self._method == 'GET':
return self.send_get(self._url,self._params,self._headers)
else:
return self.send_post(self._url,self._data,self._headers)
if __name__=='__main__':
url = 'https://oapi.t.blingabc.com/bms/admin-api/studentPreview/v1/myPreviews'
headers = {
'token': "eyJhbGciOiJIUzUxMiJ9.eyJpc3MiOiJjb20ueGRmLmJsaW5nIiwiYXVkIjoiY2xpZW50IiwidXNlcmNvZGUiOiI5NTUxNjMxNyIsImV4cCI6MTU3NDMzMDY5NiwiaWF0IjoxNTczNzI1ODk2fQ.yWaCaeOzZfVGokA7D7wrGeItcKPeyuythWIU52_1-rqZ9vEpYWRl6EYmq5thebccD0SecVpu6qLZm3NZu9DIqQ",
'Content-Type': "application/json",
'user-agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36"
}
data = {"stuNum":"955163171","page":1,"size":5,"type":2}
# url = 'https://oapi.t.blingabc.com/bms/admin-api/specialsubject/v1/save-phonics?id=285'
run = Runmain(url,'post',headers,data).run_main()
print(run)
主流程封装及错误解决调试