request模块的封装

request模块的引用和封装

背景

python+request+unittest框架的核心模块就是request模块,针对这个模块,我进行一些让自己用起来更舒适的封装,也用到了前面三篇博客写的模块。

config文件的读取博客地址

链接: https://blog.csdn.net/weixin_45076147/article/details/107492368.

数据装换文件的博客地址

链接: https://blog.csdn.net/weixin_45076147/article/details/107448820.

读取excel文件的博客地址

链接: https://blog.csdn.net/weixin_45076147/article/details/107404612.

接口关联

链接: https://blog.csdn.net/weixin_45076147/article/details/107768734.

断言和异常处理

链接: https://blog.csdn.net/weixin_45076147/article/details/108109394.

基本描述

通过封装request模块,可以实现直接根据file路径下excel表格拽写的测试用例来进行接口调用,包含了断言和异常处理

file文件的excel表

在这里插入图片描述

通过数据装换模块等到的结果


[{'case_name': 'case01', 'case_info': [{'测试用例编号': 'case01', '测试用例名称': '测试能否正确执行获取access_token接口', '用例执行': '是', '测试用例步骤': 'step_01', '接口名称': '获取access_token接口', '请求方式': 'get', '请求地址': '/cgi-bin/token', '请求参数(get)': '{"grant_type":"client_credential","appid":"博主隐藏了真真实的数据","secret":"博主隐藏了真真实的数据"}', '提交数据(post)': None, '取值方式': '无', '传值变量': None, '取值代码': None, '期望结果类型': 'json键是否存在', '期望结果': 'access_token,expires_in'}]}, {'case_name': 'case02', 'case_info': [{'测试用例编号': 'case02', '测试用例名称': '测试能否正确新增用户标签', '用例执行': '否', '测试用例步骤': 'step_01', '接口名称': '获取access_token接口', '请求方式': 'get', '请求地址': '/cgi-bin/token', '请求参数(get)': '{"grant_type":"client_credential","appid":"博主隐藏了真真实的数据","secret":"博主隐藏了真真实的数据"}', '提交数据(post)': None, '取值方式': 'json取值', '传值变量': 'token', '取值代码': '$.access_token', '期望结果类型': '正则匹配', '期望结果': '{"access_token":"(.+?)","expires_in":(.+?)}'}, {'测试用例编号': 'case02', '测试用例名称': '测试能否正确新增用户标签', '用例执行': '否', '测试用例步骤': 'step_02', '接口名称': '创建标签接口', '请求方式': 'post', '请求地址': '/cgi-bin/tags/create', '请求参数(get)': '{"access_token":${token}}', '提交数据(post)': '{"tag" : {"name" : "衡东8888"}}', '取值方式': '无', '传值变量': None, '取值代码': None, '期望结果类型': '正则匹配', '期望结果': '{"tag":{"id":(.+?),"name":"衡东8888"}}'}]}, {'case_name': 'case03', 'case_info': [{'测试用例编号': 'case03', '测试用例名称': '测试能否正确删除用户标签', '用例执行': '是', '测试用例步骤': 'step_01', '接口名称': '获取access_token接口', '请求方式': 'get', '请求地址': '/cgi-bin/token', '请求参数(get)': '{"grant_type":"client_credential","appid":"博主隐藏了真真实的数据","secret":"博主隐藏了真真实的数据"}', '提交数据(post)': None, '取值方式': 'json取值', '传值变量': 'token', '取值代码': '$.access_token', '期望结果类型': '正则匹配', '期望结果': '{"access_token":"(.+?)","expires_in":(.+?)}'}, {'测试用例编号': 'case03', '测试用例名称': '测试能否正确删除用户标签', '用例执行': '是', '测试用例步骤': 'step_02', '接口名称': '删除标签接口', '请求方式': 'post', '请求地址': '/cgi-bin/tags/delete', '请求参数(get)': '{"access_token":${token}}', '提交数据(post)': '{"tag":{"id":408}}', '取值方式': '无', '传值变量': None, '取值代码': None, '期望结果类型': 'json键值对', '期望结果': '{"errcode":0,"errmsg":"ok"}'}]}, {'case_name': None, 'case_info': [{'测试用例编号': None, '测试用例名称': None, '用例执行': None, '测试用例步骤': None, '接口名称': None, '请求方式': None, '请求地址': None, '请求参数(get)': None, '提交数据(post)': None, '取值方式': None, '传值变量': None, '取值代码': None, '期望结果类型': None, '期望结果': None}, {'测试用例编号': None, '测试用例名称': None, '用例执行': None, '测试用例步骤': None, '接口名称': None, '请求方式': None, '请求地址': None, '请求参数(get)': None, '提交数据(post)': None, '取值方式': None, '传值变量': None, '取值代码': None, '期望结果类型': None, '期望结果': None}]}]

Process finished with exit code 0

结果解析

通过数据转化模块得到的结果是一个由字典组成的列表,然后字典内部的case_info的值为excel表格的内容转换为字典,需要使用字典的内容时,可以通过列表的索引和字典的键值对取值。

代码实现

#coding:utf-8
import requests,jsonpath #需要pip install jsonpath 安装,如果是mac需要pip3
import ast #系统的第三方库,不需要下载
from config import setting #博主自己定义的库
from tools import localconfig_Utils #博主自己封装的读取config文件的库
class RequestsUtils():
    def __init__(self):
        self.hosts = localconfig_Utils.conf.URL#通过读取config模块获取url
        self.headers = {"Content-Type":"application/json;charset=utf-8"}
        self.session = requests.session() #声明一个对象,改对象保持登录
        self.temp_variables = {}#声明一个空字典

    def __get(self,get_info):
        url = self.hosts + get_info["请求地址"] #字典的键值对取值
        response = self.session.get(
            url= url,
            params= ast.literal_eval(get_info["请求参数(get)"]))# eval()函数,将字符串装换为指定格式,在这里是装换为字典,
        response.encoding = response.apparent_encoding # 将获取到的页面编码格式赋值给对象编码格式
        if get_info['取值方式'] == 'json取值':
            value = jsonpath.jsonpath(response.json(),get_info['取值代码'])[0]#使用jsonpath模块获取自己需要的数值
            self.temp_variables[get_info['传值变量']] = value
        result = {
            'code': 0,
            'response_reason':response.reason,
            'response_code':response.status_code,
            'response_headers':response.headers,
            'response_body':response.json()
        }
        return result

    def __post(self,post_info):
        url = self.hosts + post_info["请求地址"]
        response = self.session.get(
            url= url,
            headers = self.headers,
            params = {"access_token":" "},
            data = ast.literal_eval(post_info["提交数据(post)"])
        )
        # eval()函数,将字符串装换为指定格式,在这里是装换为字典,但是比较危险,所以使用安全的ast.literal_eval
        response.encoding = response.apparent_encoding # 将获取到的页面编码格式赋值给对象编码格式
        if post_info['取值方式'] == 'json取值':
            value = jsonpath.jsonpath(response.json(),post_info['取值代码'])[0]
            self.temp_variables[post_info['传值变量']] = value
        result = {
            'code': 0,
            'response_reason':response.reason,
            'response_code':response.status_code,
            'response_headers':response.headers,
            'response_body':response.json()
        }
        return result

    def request(self,step_info):
        request_type = step_info['请求方式']
        if request_type == 'get':
            result = self.__get(step_info)
        elif request_type == 'post':
            result = self.__post(step_info)
        else:
            result = {'code':3,'result':'请求方式不支持'}
        return result

    def step_request(self,step_infos):
    """
    测试用例可能存在多个步骤,故需要使用for循环遍历
    """
        for step_info in step_infos:
            print(step_info)
            result = self.request(step_info)
            if result['code'] != 0:
               break
        return result

执行结果

执行代码

if __name__ == '__main__':
	testdata = Testdatautils(setting.files_path + "\\" + "test_case.xlsx") # 读取excel的数据
	a = testdata.get_testcase_data_list() #将数据转化为字典
	print(a) #输出整个excel表格的内容转化为字典以后的值
    print("#"*20)#分割线
	get_infos = a[2]['case_info'] #获取自己需要的数据
	 print(get_infos)# 输出获取到的数据
    print("#" * 20) #分割线
	print(RequestsUtils().step_request(get_infos)) #执行接口测试用例并且输出执行结果到控制台

执行结果

[{'case_name': 'case01', 'case_info': [{'测试用例编号': 'case01', '测试用例名称': '测试能否正确执行获取access_token接口', '用例执行': '是', '测试用例步骤': 'step_01', '接口名称': '获取access_token接口', '请求方式': 'get', '请求地址': '/cgi-bin/token', '请求参数(get)': '{"grant_type":"client_credential","appid":"博主隐藏了真真实的数据","secret":"博主隐藏了真真实的数据"}', '提交数据(post)': None, '取值方式': '无', '传值变量': None, '取值代码': None, '期望结果类型': 'json键是否存在', '期望结果': 'access_token,expires_in'}]}, {'case_name': 'case02', 'case_info': [{'测试用例编号': 'case02', '测试用例名称': '测试能否正确新增用户标签', '用例执行': '否', '测试用例步骤': 'step_01', '接口名称': '获取access_token接口', '请求方式': 'get', '请求地址': '/cgi-bin/token', '请求参数(get)': '{"grant_type":"client_credential","appid":"博主隐藏了真真实的数据","secret":"博主隐藏了真真实的数据"}', '提交数据(post)': None, '取值方式': 'json取值', '传值变量': 'token', '取值代码': '$.access_token', '期望结果类型': '正则匹配', '期望结果': '{"access_token":"(.+?)","expires_in":(.+?)}'}, {'测试用例编号': 'case02', '测试用例名称': '测试能否正确新增用户标签', '用例执行': '否', '测试用例步骤': 'step_02', '接口名称': '创建标签接口', '请求方式': 'post', '请求地址': '/cgi-bin/tags/create', '请求参数(get)': '{"access_token":${token}}', '提交数据(post)': '{"tag" : {"name" : "衡东8888"}}', '取值方式': '无', '传值变量': None, '取值代码': None, '期望结果类型': '正则匹配', '期望结果': '{"tag":{"id":(.+?),"name":"衡东8888"}}'}]}, {'case_name': 'case03', 'case_info': [{'测试用例编号': 'case03', '测试用例名称': '测试能否正确删除用户标签', '用例执行': '是', '测试用例步骤': 'step_01', '接口名称': '获取access_token接口', '请求方式': 'get', '请求地址': '/cgi-bin/token', '请求参数(get)': '{"grant_type":"client_credential","appid":"博主隐藏了真真实的数据","secret":"博主隐藏了真真实的数据"}', '提交数据(post)': None, '取值方式': 'json取值', '传值变量': 'token', '取值代码': '$.access_token', '期望结果类型': '正则匹配', '期望结果': '{"access_token":"(.+?)","expires_in":(.+?)}'}, {'测试用例编号': 'case03', '测试用例名称': '测试能否正确删除用户标签', '用例执行': '是', '测试用例步骤': 'step_02', '接口名称': '删除标签接口', '请求方式': 'post', '请求地址': '/cgi-bin/tags/delete', '请求参数(get)': '{"access_token":${token}}', '提交数据(post)': '{"tag":{"id":408}}', '取值方式': '无', '传值变量': None, '取值代码': None, '期望结果类型': 'json键值对', '期望结果': '{"errcode":0,"errmsg":"ok"}'}]}, {'case_name': None, 'case_info': [{'测试用例编号': None, '测试用例名称': None, '用例执行': None, '测试用例步骤': None, '接口名称': None, '请求方式': None, '请求地址': None, '请求参数(get)': None, '提交数据(post)': None, '取值方式': None, '传值变量': None, '取值代码': None, '期望结果类型': None, '期望结果': None}, {'测试用例编号': None, '测试用例名称': None, '用例执行': None, '测试用例步骤': None, '接口名称': None, '请求方式': None, '请求地址': None, '请求参数(get)': None, '提交数据(post)': None, '取值方式': None, '传值变量': None, '取值代码': None, '期望结果类型': None, '期望结果': None}]}]
####################
[{'测试用例编号': 'case03', '测试用例名称': '测试能否正确删除用户标签', '用例执行': '是', '测试用例步骤': 'step_01', '接口名称': '获取access_token接口', '请求方式': 'get', '请求地址': '/cgi-bin/token', '请求参数(get)': '{"grant_type":"client_credential","appid":"博主隐藏了真真实的数据","secret":"博主隐藏了真真实的数据"}', '提交数据(post)': None, '取值方式': 'json取值', '传值变量': 'token', '取值代码': '$.access_token', '期望结果类型': '正则匹配', '期望结果': '{"access_token":"(.+?)","expires_in":(.+?)}'}, {'测试用例编号': 'case03', '测试用例名称': '测试能否正确删除用户标签', '用例执行': '是', '测试用例步骤': 'step_02', '接口名称': '删除标签接口', '请求方式': 'post', '请求地址': '/cgi-bin/tags/delete', '请求参数(get)': '{"access_token":${token}}', '提交数据(post)': '{"tag":{"id":408}}', '取值方式': '无', '传值变量': None, '取值代码': None, '期望结果类型': 'json键值对', '期望结果': '{"errcode":0,"errmsg":"ok"}'}]
####################
{'code': 0, 'response_reason': 'OK', 'response_code': 200, 'response_headers': {'Connection': 'keep-alive', 'Date': 'Tue, 28 Jul 2020 10:12:35 GMT', 'Content-Type': 'application/json; encoding=utf-8', 'RetKey': '11', 'LogicRet': '40001', 'Content-Length': '113'}, 'response_body': {'errcode': 40001, 'errmsg': 'invalid credential, access_token is invalid or not latest hints: [FINdnjuhE-JeCnJA!]'}}

添加了异常处理和断言以后的代码块

#coding:utf-8
import jsonpath
import requests,ast,re
from requests.exceptions import RequestException
from requests.exceptions import ProxyError
from requests.exceptions import ConnectionError

from tools.check_utils import CheckUtils #CheckUtils为博主封装的断言模块
from config import setting
from tools import localconfig_Utils
from tools.testdata_utils import Testdatautils


class RequestsUtils():
    def __init__(self):
        self.hosts = localconfig_Utils.conf.URL
        self.headers = {"Content-Type":"application/json;charset=utf-8"}
        self.session = requests.session()
        self.temp_variables = {}

    def __get(self,get_info):
        try:
            url = self.hosts + get_info["请求地址"]
            response = self.session.get(
                url= url,
                params= ast.literal_eval(get_info["请求参数(get)"]))# eval()函数,将字符串装换为指定格式,在这里是装换为字典
            response.encoding = response.apparent_encoding # 将获取到的页面编码格式赋值给对象编码格式
            if get_info['取值方式'] == 'json取值':
                value = jsonpath.jsonpath(response.json(),get_info['取值代码'])[0]
                self.temp_variables[get_info['传值变量']] = value
            elif get_info['取值方式'] == '正则取值':
                value =re.findall(get_info["取值代码"],response.text)[0]
                self.temp_variables[get_info['传值变量']] = value
            result = CheckUtils(response).run_check(get_info['期望结果类型'], get_info['期望结果'])
            #根据博主自己封装的CheckUtils类的方法进行断言
        except ProxyError as e:
            result = {'code': 4, 'result': '[%s]请求:代理错误异常' % (get_info["接口名称"])}
        except ConnectionError as e:
            result = {'code': 4, 'result': '[%s]请求:连接超时异常,解决方案:查看是否断网,或者打开了代理' % (get_info["接口名称"])}
        except RequestException as e:
            result = {'code': 4, 'result': '[%s]请求:Request异常,原因:%s' % (get_info["接口名称"], e.__str__())}
        except KeyError as e:
            result = {'code': 4, 'result': '[%s]请求:excel的表头没有【%s】' % (get_info["接口名称"],e.__str__())}
        except Exception as e:
            result = {'code': 4, 'result': '[%s]请求:系统异常,原因:%s' % (get_info["接口名称"], e.__str__())}
        return result

    def __post(self,post_info):
        try:
            url = self.hosts + post_info["请求地址"]
            response = self.session.get(
                url= url,
                headers = self.headers,
                params = ast.literal_eval(post_info["请求参数(get)"]),
                data = ast.literal_eval(post_info["提交数据(post)"])
            )
            # eval()函数,将字符串装换为指定格式,在这里是装换为字典,但是比较危险,所以使用安全的ast.literal_eval
            response.encoding = response.apparent_encoding # 将获取到的页面编码格式赋值给对象编码格式
            if post_info['取值方式'] == 'json取值':
                value = jsonpath.jsonpath(response.json(),post_info['取值代码'])[0]
                self.temp_variables[post_info['传值变量']] = value
            elif post_info['取值方式'] == '正则取值':
                value =re.findall(post_info["取值代码"],response.text)[0]
                self.temp_variables[post_info['传值变量']] = value
            result = CheckUtils(response).run_check(post_info['期望结果类型'], post_info['期望结果'])
            #根据博主自己封装的CheckUtils类的方法进行断言
        except ProxyError as e:
            result = {'code': 4, 'result': '[%s]请求:代理错误异常' % (post_info["接口名称"])}
        except ConnectionError as e:
            result = {'code': 4, 'result': '[%s]请求:连接超时异常,解决方案:查看是否断网,或者打开了代理' % (post_info["接口名称"])}
        except RequestException as e:
            result = {'code': 4, 'result': '[%s]请求:Request异常,原因:%s' % (post_info["接口名称"], e.__str__())}
        except KeyError as e:
            result = {'code': 4, 'result': '[%s]请求:excel的表头没有【%s】' % (post_info["接口名称"], e.__str__())}
        except Exception as e:
            result = {'code': 4, 'result': '[%s]请求:系统异常,原因:%s' % (post_info["接口名称"], e.__str__())}
        return result

    def request(self,step_info):
        try:
            request_type = step_info['请求方式']
            param_variable_list = re.findall('\\${\w+}', step_info["请求参数(get)"])
            if param_variable_list:
                for param_variable in param_variable_list:
                    step_info["请求参数(get)"] = step_info["请求参数(get)"].replace(param_variable,
                                                                            '"%s"' % self.temp_variables.get(
                                                                                param_variable[
                                                                                2:-1]))  # '"%s"' 通过格式化给值加双引号
            if request_type == 'get':
                result = self.__get(step_info)
            elif request_type == 'post':
                param_variable_list = re.findall('\\${\w+}', step_info["提交数据(post)"])
                if param_variable_list:
                    for param_variable in param_variable_list:
                        step_info["提交数据(post)"] = step_info["提交数据(post)"].replace(param_variable,
                                                                                '"%s"' % self.temp_variables.get(
                                                                                    param_variable[
                                                                                    2:-1]))  # '"%s"' 通过格式化给值加双引号
                result = self.__post(step_info)
            else:
                result = {'code':3,'result':'请求方式不支持'}
        except Exception as e:
            result = {'code':4,'result':'用例编号[%s]的[%s]步骤出现系统异常,原因:%s'%(step_info['测试用例编号'],step_info["测试用例步骤"],e.__str__())}
        return result

    def step_request(self,step_infos):
        for step_info in step_infos:
            result = self.request(step_info)
            if result['code'] != 0:
               break
        return result
if __name__ == '__main__':
    testdata = Testdatautils(setting.files_path + "\\" + "test_case.xlsx")
    a = testdata.get_testcase_data_list()
    get_infos = a[0]['case_info']
    print(get_infos)
    print(RequestsUtils().step_request(get_infos))


执行结果

[{'测试用例编号': 'case01', '测试用例名称': '测试能否正确执行获取access_token接口', '用例执行': '是', '测试用例步骤': 'step_01', '接口名称': '获取access_token接口', '请求方式': 'get', '请求地址': '/cgi-bin/token', '请求参数(get)': '{"grant_type":"client_credential","appid":"博主隐藏了真真实的数据","secret":"博主隐藏了真真实的数据"}', '提交数据(post)': None, '取值方式': '无', '传值变量': None, '取值代码': None, '期望结果类型': 'json键是否存在', '期望结果': 'access_token,expires_in'}]
{'code': 0, 'response_reason': 'OK', 'response_code': 200, 'response_headers': {'Connection': 'keep-alive', 'Content-Type': 'application/json; encoding=utf-8', 'Date': 'Wed, 19 Aug 2020 13:42:48 GMT', 'Content-Length': '194'}, 'response_body': '{"access_token":"博主隐藏了真真实的数据","expires_in":7200}', 'check_result': True, 'message': "断言成功,接口的响应值中键名包含了['access_token', 'expires_in']"}

Process finished with exit code 0

总结

整体上将框架的核心封装完成,包含了断言,异常处理

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值