一:发送HTTP请求模块封装
1. 使用requests库访问接口
url = 'http://api.lemonban.com/futureloan/member/register'
data = {
'mobile_phone': 1586****777,
'pwd': '12345678',
'type': 0,
'reg_name': '心蓝'
}
headers = {
'X-Lemonban-Media-Type': 'lemonban.v1'
}
response = requests.post(url=url, json=data, headers=headers)
response.json()
{'code': 0,
'msg': 'OK',
'data': {'id': 262312, 'reg_name': '心蓝', 'mobile_phone': '1586****777'},
'copyright': 'Copyright 柠檬班 © 2017-2019 湖南省零檬信息技术有限公司 All Rights Reserved'}
2. 功能分析
可以根据用例数据动态的
- 向不同url发送http请求
- 发送各种方法的http请求
- 可以携带各种参数
3. 封装成函数
封装思路:
- 输入参数为url,method,和需要携带的各种参数以及请求头等,与requests的原生形参一致
- 可以使用关键字动态参数解决参数过多的问题
- 根据传入的method,发送对应的请求
在common
文件夹下创建make_requests.py
模块,在其中编写如下函数:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2021/11/24 21:19
# @Author : shisuiyi
# @File : make_requests.py
# @Software: win10 Tensorflow1.13.1 python3.9
import requests
def send_http_request(url, method='GET', **kwargs):
"""
发送http请求
@param url: 接口url
@param method:http 请求方法
@param kwargs:接受request原生的关键字参数
@return 响应对象
"""
# 将方法统一转为小写
method = method.lower()
# 根据传入的方法名发送对应的请求
if method == 'get':
res = requests.get(url, **kwargs)
if method == 'post':
res = requests.post(url, **kwargs)
elif method == 'put':
res = requests.put(url, **kwargs)
elif method == 'delete':
res = requests.delete(url, **kwargs)
elif method == 'patch':
res = requests.patch(url, **kwargs)
else:
raise ValueError('请输入正确的请求方法')
return res
# 代码逻辑请求,但是冗余,菜鸟级的代码。面向对象里的反射,改写上面的代码
if __name__ == '__main__':
url = 'http://api.lemonban.com/futureloan/member/register'
method = 'POST'
request_data = {
'json': {
'mobile_phone': 1586****777,
'pwd': '12345678',
'type': 0,
'reg_name': '心蓝'
},
'headers': {
'X-Lemonban-Media-Type': 'lemonban.v1'
}
}
headers = {
'X-Lemonban-Media-Type': 'lemonban.v1'
}
data = send_http_request(url, method, **request_data) # 在传递实参时,可以通过 ** 对字典对象进行解包。解包成多个关键字参数
print(data.json())
代码逻辑请求,但是冗余,菜鸟级的代码。面向对象里的反射,改写上面的代码
getattr(requests, 'get')() # 返回一个对象给定名称的属性
<function requests.api.get(url, params=None, **kwargs)>
同样:
requests.get()
<function requests.api.get(url, params=None, **kwargs)>
所以可以将上述复杂的逻辑使用反射简化
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2021/11/24 21:19
# @Author : shisuiyi
# @File : make_requests.py
# @Software: win10 Tensorflow1.13.1 python3.9
import requests
def send_http_request(url, method='GET', **kwargs):
"""
发送http请求
@param url: 接口url
@param method:http 请求方法
@param kwargs:接受request原生的关键字参数
@return 响应对象
"""
# 将方法统一转为小写
method = method.lower()
# # 根据传入的方法名发送对应的请求
# if method == 'get':
# res = requests.get(url, **kwargs)
# if method == 'post':
# res = requests.post(url, **kwargs)
# elif method == 'put':
# res = requests.put(url, **kwargs)
# elif method == 'delete':
# res = requests.delete(url, **kwargs)
# elif method == 'patch':
# res = requests.patch(url, **kwargs)
# else:
# raise ValueError('请输入正确的请求方法')
# return res.json()
# # 代码逻辑请求,但是冗余,菜鸟级的代码。面向对象里的反射,改写上面的代码
return getattr(requests, method)(url, **kwargs)
if __name__ == '__main__':
url = 'http://api.lemonban.com/futureloan/member/register'
method = 'POST'
request_data = {
'json': {
'mobile_phone': 1586****777,
'pwd': '12345678',
'type': 0,
'reg_name': '心蓝'
},
'headers': {
'X-Lemonban-Media-Type': 'lemonban.v1'
}
}
headers = {
'X-Lemonban-Media-Type': 'lemonban.v1'
}
data = send_http_request(url, method, **request_data) # 在传递实参时,可以通过 ** 对字典对象进行解包。解包成多个关键字参数
print(data.json())
二、注册接口测试
1. 步骤
1. 测试数据
- 读取excel里的用例数据
- 解析请求数据,解析期望数据
2. 测试流程
- 根据请求数据发送请求并获取响应结果
3. 断言
- 响应状态码断言
- 响应数据断言
- 数据库断言
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2021/11/28 13:02
# @Author : shisuiyi
# @File : test_register.py
# @Software: win10 Tensorflow1.13.1 python3.9
import json
import unittest
from unittestreport import ddt, list_data
import setting
from common import get_data_from_excel
from common import logger
from common import send_http_request
# 读取测试用例数据
cases = get_data_from_excel(setting.TEST_DATA_FILE)
@ddt
class RegisterTestCase(unittest.TestCase):
@classmethod
def setUpClass(cls) -> None:
logger.info('===========注册接口开始测试===========')
@classmethod
def tearDownClass(cls) -> None:
logger.info('===========注册接口结束测试===========')
@list_data(cases)
def test_register(self, item):
logger.info('>>>>>>>用例{}开始执行>>>>>>>>'.format(item['title']))
# 1. 处理测试数据
# 把请求参数处理好,request_data是一个json字符串,怎么通过封装好的发送请求的函数发送
# expect_data也是一个json字符串,也需要loads成python对象
request_data = json.loads(item['request'])
expect_data = json.loads(item['expect_data'])
# 2. 测试步骤
# 发送请求
res = send_http_request(item['url'], item['method'], **request_data)
print(res.json())
# 3. 断言
# 3.1 断言响应状态码
self.assertEqual(item['status_code'], res.status_code)
logger.info('<<<<<<<<<用例{}测试结束<<<<<<<'.format(item['title']))
# 3.2 断言响应数据
if item['res_type'].lower() == 'json':
res = res.json()
elif item['res_type'].lower() == 'html':
# 扩展思路
res = res.text
self.assertEqual(expect_data, {'code': res['code'], 'msg': res['msg']})
# 3.3 数据库断言后面的任务
if __name__ == '__main__':
unittest.main()
评论