资讯详情

API自动化工具之案例解析

项目GitHub地址:GitHub - muzili0903/APIframework

如果您有任何问题,请留言。当然,如果你认为写得好,你可以收集或推荐它。如果可以的话,麻烦GitHub帮个小星星!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

基于此框架Python Pytest Requests Allure Yaml Json实现接口业务相关的自动化测试,使用此框架,您只需要抓取接口数据包,无需编写任何代码。关于框架的使用和已实现的内容,请参阅框架的第一篇介绍:API自动化工具雏形_YiHong_Li的博客-CSDN博客

案例分析分为请求头分析和请求报文分析。通过对请求报文和请求报文分析函数的特定格式script脚本接口文档转换json报文格式

请求头分析:

请求头中固定定参数优先考虑script从配置文件中获法获得脚本。(请求头支持用户参数化)

def ini_request_headers(request_headers: dict, test_data: dict, con) -> dict:     """     请求头处理     :param request_headers:     :param test_data     :return:     """     try:         default_headers = dict(con.get_items('request_headers'))         default_project = dict(con.get_items('project'))     except Exception as e:         logging.error("配置文件request_headers 或 default_project 不存在: >>>{default_headers}, {default_project}".format(             default_headers=default_headers, default_project=default_project))         logging.error("报错信息: >>>{}".format(e))     # headers     method = request_headers.get('Method') or default_headers.get('Method')     content_type = request_headers.get('Content-Type') or default_headers.get('Content-Type')     user_agent = request_headers.get('User-Agent') or default_headers.get('User-Agent')     connection = request_headers.get('Connection') or default_headers.get('Connection')     timeout = request_headers.get('timeout') or default_headers.get('timeout')     cookie = request_headers.get('cookie') or default_headers.get('cookie')     save_cookie = request_headers.get('save_cookie') or default_headers.get('save_cookie')     sleep_time = request_headers.get('sleep_time') or default_headers.get('sleep_time')     path = request_headers.get('path') or default_headers.get('path')     # project 上游与管理台的交互兼容     base_url = request_headers.get('base_url') or default_project.get('base_url')     env = request_headers.get('env') or default_project.get('env')     logging.info("request_headers处理前: >>>{}".format(request_headers))     try:         header = {'Method': method, 'Content-Type': content_type, 'User-Agent': user_agent, 'Connection': connection,                   'timeout': int(timeout), 'cookie': cookie, 'save_cookie': save_cookie, 'path': path,                   'base_url': base_url, 'env': env, 'sleep_time': int(sleep_time)}         header = eval(replaceData.replace_user_var(str(header), test_data))         request_headers.update(header)     except Exception as e:         logging.error("request_headers处理失败: >>>{}".format(e))     logging.info("request_headers处理后: >>>{}".format(request_headers))     return request_headers

用户参数化:

 def replace_user_var(case, data: dict):     """     替换请求报文中的用户参数值 ${变量名}     :param case: 用例报文     :param data: 用例数据     :return:     """     if re.search('\$\{.*?\}', case) is not None:         res = re.findall('\$\{.*?\}', case)     else:         return case     try:         for index in range(len(res)):             var = res[index].split('{')[1].split[0]             case = case.replace(res[index], str(data[var]), 1)     except KeyError:         logging.error("不能获得变量值: >>>{}".format(var))     return case  

请求报文分析:

请求报文获取script脚本中request_body下 parameter 值,通过parameter读取相应的请求报纸内容(yaml文件夹下相应的请求报告yaml目前支持文件)请求报文:用户参数化、系统函数参数化、请求报文参数化等。( 具体参数化方法可查阅第一篇文章:API自动化工具雏形_YiHong_Li的博客-CSDN博客)

def ini_params(test_info: dict, test_data: dict) -> dict:     """     初始化报文     :param test_info:测试报文     :param test_data: 测试数据     :return:     """     logging.info("body处理前: >>>{}".format(test_info))     # 用户定制参数     if re.search('\$\{.*?\}', str(test_info)) is not None:         test_info = eval(replaceData.replace_user_var(str(test_info), test_data))     # 系统函数参数化     if re.search('\$\(f.*?\)', str(test_info)) is not None:         test_info = eval(replaceData.replace_func(str(test_info)))     # 用户自定义函数参数化     if re.search('\$\(u.*?\)', str(test_info)) is not None:         test_info = eval(replaceData.replace_user_func(str(test_info)))     # 参数值从请求报获得     if re.search('\$Req\{.*?\}', str(test_info)) is not None:         test_info = eval(replaceData.replace_req(str(test_info)))     # 从响应报获得参数值     if re.search('\$Resp\{.*?\}', str(test_info)) is not None:         test_info = eval(replaceData.replace_resp(str(test_info)))     # 参数值从数据库中获取     if re.search('\$DB\{.*?\}', str(test_info)) is not None:         test_info = eval(replaceData.replace_db(str(test_info), test_data))     logging.info("body处理后: >>>{}".format(test_info))     return tes_info

系统函数参数化:

def replace_func(case):
    """
    替换请求报文中的函数变量值 $(f函数名)
    :param case:
    :return:
    """
    if re.search('\$\(f.*?\)', case) is not None:
        res = re.findall('\$\(f.*?\)', case)
    else:
        return case
    try:
        for index in range(len(res)):
            func_params = res[index].split('(', 1)[1].split(')', 1)[0]
            if "::" in func_params:  # 带参函数
                func_name, params = func_params.split("::")
                func = func_name + '(' + params + ')'
            else:  # 不带参函数
                func = func_params + '()'
            func = eval('sysFunc.' + func)
            case = case.replace(res[index], func, 1)
    except AttributeError:
        logging.error("获取不到系统函数: >>>{}".format(func))
    return case

请求报文参数化:

def replace_req(case):
    """
    从其它接口的请求报文中替换请求报文中的参数值 $Req{接口名.变量名}
    :param case:
    :return:
    """
    if re.search('\$Req\{.*?\}', case) is not None:
        res = re.findall('\$Req\{.*?\}', case)
    else:
        return case
    # 测试专用
    # GolStatic.set_file_temp('test', 'request_body',
    #                         {'businessNo': '123456', 'j': [{'businessNo': '1111'}, {'businessNo': '2222'}]})
    try:
        for index in range(len(res)):
            var = res[index].split('{')[1].split('}')[0]
            filename, var_name = var.split('.', 1)
            request_body = GolStatic.get_file_temp(filename=filename, key='request_body')
            value = jsonpath(request_body, var_name)
            if value:
                case = case.replace(res[index], value[0], 1)
            else:
                case = case.replace(res[index], '', 1)
                logging.error("获取不到请求报文字段值: >>>{}".format(var_name))
    except KeyError:
        logging.error("获取不到请求报文字段值: >>>{}".format(var))
    except ValueError:
        logging.error("jsonpath表达式有误: >>>{}".format(var))
    return case

结果展示:

2022-06-16 08:26:15,854 - initializeParam.py - INFO: body处理前>>>{'appId': '${appId}', 'appKey': '${appKey}', 'data': {'invoiceAmt': 610.0, 'immediateInvoice': 1, 'payTaxpayerName': '${payTaxpayerName}', 'invoiceHead': 1, 'bizId': 'biz$(fdate)$(ftime)', 'invoiceType': 3, 'remarks': '票面备注:客户名称:${payTaxpayerName}, bizId=biz$(fdate)$(ftime)$(fnum::2)', 'taxpayerCode': '${taxpayerCode}', 'businessNo': '$(fdate)$(ftime)$(fnum::4)', 'detailList': [{'standards': 'MT-TZBKC01', 'taxRate': 0.13, 'taxUnitPrice': 180.0, 'businessNo': '$(fdate)$(ftime)$(fnum::2)', 'goodCount': 1, 'goodUnit': '台', 'bizDetailId': 'bdid$(fnum::11)', 'amtContainTax': 180.0, 'taxCode': '1080422', 'goodsName': 'Micca 炊具'}, {'standards': 'MP-SJ20W101', 'taxRate': 0.13, 'taxUnitPrice': 430.0, 'businessNo': '$(fdate)$(ftime)$(fnum::2)', 'goodCount': 1, 'goodUnit': '台', 'bizDetailId': 'bdid$(fnum::11)', 'amtContainTax': 430.0, 'taxCode': '107060112', 'goodsName': 'Midea/美的 餐饮具'}]}}
2022-06-16 08:26:15,854 - initializeParam.py - INFO: body处理后>>>{'appId': 'IBCP', 'appKey': '123456', 'data': {'invoiceAmt': 610.0, 'immediateInvoice': 1, 'payTaxpayerName': 'muzili_blue', 'invoiceHead': 1, 'bizId': 'biz20220616082615', 'invoiceType': 3, 'remarks': '票面备注:客户名称:muzili_blue, bizId=biz2022061608261516', 'taxpayerCode': '4429999441', 'businessNo': '202206160826153552', 'detailList': [{'standards': 'MT-TZBKC01', 'taxRate': 0.13, 'taxUnitPrice': 180.0, 'businessNo': '2022061608261574', 'goodCount': 1, 'goodUnit': '台', 'bizDetailId': 'bdid52138607243', 'amtContainTax': 180.0, 'taxCode': '1080422', 'goodsName': 'Micca 炊具'}, {'standards': 'MP-SJ20W101', 'taxRate': 0.13, 'taxUnitPrice': 430.0, 'businessNo': '2022061608261533', 'goodCount': 1, 'goodUnit': '台', 'bizDetailId': 'bdid49965521408', 'amtContainTax': 430.0, 'taxCode': '107060112', 'goodsName': 'Midea/美的 餐饮具'}]}}

标签: 二极管tv02w101b

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

 锐单商城 - 一站式电子元器件采购平台  

 深圳锐单电子有限公司