一:发送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. 功能分析

可以根据用例数据动态的

  1. 向不同url发送http请求
  2. 发送各种方法的http请求
  3. 可以携带各种参数

3. 封装成函数

封装思路:

  1. 输入参数为url,method,和需要携带的各种参数以及请求头等,与requests的原生形参一致
  2. 可以使用关键字动态参数解决参数过多的问题
  3. 根据传入的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. 测试数据

  1. 读取excel里的用例数据
  2. 解析请求数据,解析期望数据

2. 测试流程

  1. 根据请求数据发送请求并获取响应结果

3. 断言

  1. 响应状态码断言
  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()