2

python实战-基于正交实验(工具:allpairs)自动生成接口异常测试用例 - wan了个蛋

 1 year ago
source link: https://www.cnblogs.com/qtclm/p/17076588.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

目前支持的功能

1.基于不同的参数类型(str、int、float、bool、list、tuple、dict、set、None、date、datetime、time、timestamp)自动生成正交测试用例
2.可以自定义参数长度与内容,方便覆盖边界值测试
3.提供自定义过滤参数组合的入口,方便自定义

1.抓取api信息(目前公司用的swagger): https://www.cnblogs.com/qtclm/p/17049176.html ,uri、method、params、response,解析完成后写入excle
2.读取抓取完毕的api信息,处理为allpairs所需要的ordereddict
3.调用allpairs工具生成测试用例
4.解析allpairs生成的测试用例(输出为字符串),并处理为dict
5.处理完毕后写入excel

1.根据接口响应实现自动断言
2.增加其他接口平台的api抓取(openapi、eolink等)
3.增加其他自动化生成用例的方法(有效、无效等价类,流量回放等)
4.集成到平台

遇到的问题

1.allpairs只支持两个以上的参数生成,因为参数只有一个时,需要自行处理
2.参数为json嵌套时,allpairs输出的参数需要额外特殊处理,这块也是最麻烦的地方
3.可变类型在循环过程中尽量使用深拷贝对象,避免循环运行中被意外修改
4.类变量、实例变量需要合理运用,例如循环时需要合理的进行初始化

# _*_ coding: UTF-8 _*_
"""
@project -> file : city-test -> rr
@Author          : qinmin.vendor
@Date            : 2023/1/29 19:44
@Desc            : 自动生成接口测试用例:支持正交实验,等价类,边界值
"""

import copy
import json
import os
import random
import re
import sys
from collections import OrderedDict
from allpairspy import AllPairs
from utils.operation_datas import operationExcle
import math
from utils.time_utils import timeUtil
from utils.wrapper_util import exec_time_wrapper
from inspect import isfunction

from faker import Faker
'''faker使用教程:https://blog.csdn.net/qq_42412061/article/details/122997802'''

class autoGenrateApiCaseAllpairspy(object):

    time_util = timeUtil()
    fake = Faker(locale="zh_cn")  # 指定语言为中文

    CONST_MAX_STRING_LENGTH = 100
    CONST_MIN_STRING_LENGTH = 1
    # 生成字符串相关的数据
    # special_chars是否包含特殊字符;digits是否包含数字;upper_case是否包含大写字母,lower_case是否包含小写字母
    special_character = fake.password(length=8, special_chars=True, digits=False, upper_case=False,
                                      lower_case=False)  # 生成随机特殊字符
    random_str = fake.paragraph()  # 生成随机字符
    random_str_max = random_str * math.ceil(CONST_MAX_STRING_LENGTH / len(random_str))
    phone_number = fake.phone_number()  # 生成随机电话号码

    # 生成时间相关的数据
    random_date = fake.date(pattern="%Y-%m-%d", end_datetime=None)  # 生成随机日期
    random_start_datetime = time_util.adjust_time(num=-30)
    random_end_datetime = time_util.adjust_time(num=0)
    random_start_timestamp_millisecond = time_util.adjust_time(num=-30, is_timestamp=True, millisecond=True)
    random_end_timestamp_millisecond = time_util.adjust_time(num=0, is_timestamp=True, millisecond=True)
    random_start_timestamp = time_util.adjust_time(num=-30, is_timestamp=True, millisecond=False)
    random_end_timestamp = time_util.adjust_time(num=0, is_timestamp=True, millisecond=False)

    # 生成int与float相关的数据
    random_int = random.randint(1, 100)
    random_float = round(random.random(), 6) + random_int  # 生成随机字符
    random_int_max = str(random_int) * math.ceil(CONST_MAX_STRING_LENGTH / len(str(random_int)))
    random_float_max = str(str(random_float) *
        math.ceil(CONST_MAX_STRING_LENGTH / len(str(random_float).replace('.', '')))).\
       replace('.','') + "." + str(random_int)


    STRING_ENUM = ["", None, random_str, special_character,
                   random_str_max[:CONST_MAX_STRING_LENGTH], random_str[:CONST_MIN_STRING_LENGTH],
                   random_start_datetime, random_end_datetime, random_date]

    INT_FLOAT_ENUM = [0, None, special_character, random_int, random_float,
                      int(random_int_max[:CONST_MAX_STRING_LENGTH]),
                      int(str(random_int)[:CONST_MIN_STRING_LENGTH]), int(random_float_max[:CONST_MAX_STRING_LENGTH]),
                      int(str(random_float)[:CONST_MIN_STRING_LENGTH]), random_start_timestamp,
                      random_start_timestamp_millisecond, random_end_timestamp, random_end_timestamp_millisecond]
    LIST_ENUM=[[], None, [{}]]
    BOOL_ENUM=[None, False, True,"true","false"]
    OBJECT_ENUM=[None,{}]
    NULL_ENUM=[None,"null"]

    # 定义接口字段生成的类型与枚举
    CONST_TYPE_ENUM = {
        str: STRING_ENUM,"string": STRING_ENUM,
        int: INT_FLOAT_ENUM,"integer": INT_FLOAT_ENUM,"number": INT_FLOAT_ENUM,
        None: NULL_ENUM, "NONE": NULL_ENUM,"null": NULL_ENUM,
        float: INT_FLOAT_ENUM,"double": INT_FLOAT_ENUM,
        bool: BOOL_ENUM,'bool': BOOL_ENUM,"boolean": BOOL_ENUM,
        dict: OBJECT_ENUM,'object': OBJECT_ENUM,set: LIST_ENUM,list: LIST_ENUM,'array': LIST_ENUM,
    }

    CONST_TYPE_ENUM_COPY = copy.deepcopy(CONST_TYPE_ENUM)

    is_array = False #判断参数传入的参数是不是list

    params_key_list = [] #判断参数的key对应的value是不是list类型,如果是,就将key存进此对象
    extra_cases = [] #存放额外的case,请求参数中的key嵌套json的情况

    excle_path = './'
    excle_name_params_field_detail = 'auto_genrate_api_case_allpairspy_params_field_detail.xlsx'
    excle_name_params_obj = 'auto_genrate_api_case_allpairspy_params_obj_5.xlsx'
    # excle_name_cases_data = 'maint-api.xlsx'
    excle_name_cases_data = 'maint-apiv2-api-docs.xlsx'

    # 递归解析json,原文:https://blog.csdn.net/qq_45662588/article/details/122265447
    read_excle_case_field_desc={'case':0,'uri':1,'method':2,"params_path":3,"params_body":5,"response_body":7,"skip":9}
    # 数据处理前的case表头,写入excle中最终会删除params_path,且params_body替换为params && response_body替换为expected
    write_excle_case_field_desc={'case':0,'uri':1,'method':2,'params_path':3,'params_body':4,'response_body':5,'skip':6}

    @classmethod
    def custom_valid_combination(cls,row):
        """
        自定义过滤条件,返回false的条件不会出现在组合中
        """
        n = len(row)
        if n > 1:
            if row[0] in (None,'',""):
                return False
        return True

    # 指定:自定义过滤函数
    all_pairs_filter_func=custom_valid_combination
    if not (isfunction(all_pairs_filter_func) or isinstance(all_pairs_filter_func,(classmethod,staticmethod))) :
        raise Exception(f"all_pairs_filter_func对象必须是一个方法:{all_pairs_filter_func}")

    @classmethod
    def read_all_cases_data(cls):
        cases_data_obj=operationExcle(excle_path=cls.excle_path,excle_name=cls.excle_name_cases_data)
        lines=cases_data_obj.get_lines()+1
        case_list=[]
        for i in range(lines):
            # yield cases_data_obj.get_row_data(i+1)
            values=cases_data_obj.get_row_data(i+1)
            out_values=[]
            for i in cls.read_excle_case_field_desc:
                out_values.append(values[cls.read_excle_case_field_desc[i]])
            if out_values[0] is not None:
                case_list.append(out_values)
        return case_list

    @classmethod
    def dict_parse_generator(cls,params,pre=None):
        '''递归解析json,如果key为对应的值是list且list中的元素不是dict,则不返回'''
        pre = pre[:] if pre else []  # 纪录value对应的key信息
        # print("params:",params)
        if isinstance(params,list) :
            params=params[0]
        if isinstance(params, dict):
            for key, value in params.items():
                if isinstance(value, dict):
                    if len(value) > 0:
                        for d in cls.dict_parse_generator(value, pre + [key]):
                            yield d
                    else:
                        yield pre + [key, '{}']
                elif isinstance(value, (list, tuple)):
                    if len(value) > 0:
                        for index, v in enumerate(value):
                            # 纪录list的下标与key,方便动态提取
                            # print("index",index)
                            for d in cls.dict_parse_generator(v, pre + [key, str(index)]):
                                yield d
                    else:
                        yield pre + [key, '[]'] if isinstance(value,list) else pre + [key,'()']

                else:
                    yield pre + [key, value]

    @classmethod
    def api_prams_convert(cls, params_info):
        '''根据参数与参数类型转换为预期定义的数据类型定义的枚举'''

        def get_params_field_type(params_field_value):
            if str(params_field_value).startswith('"') and str(params_field_value).endswith('"'):
                _type = 'string' or 'str'
            elif str(params_field_value).startswith('{') and str(params_field_value).endswith("}"):
                _type = 'object' or 'dict'
            elif str(params_field_value).startswith('[') and str(params_field_value).endswith(']'):
                _type = 'array' or 'list'
            elif str(params_field_value) in ('0', '0.0'):
                _type = 'number' or 'int'
            elif str(params_field_value) in ("true", 'false', 'True', 'False'):
                _type = 'boolean' or 'bool'
            elif str(params_field_value) in ('None', 'null', 'nil'):
                _type = 'null' or 'None'
            else:
                _type = 'string' or 'str'
            return _type

        def replace_params_values(params_info):
            '''替换参数所有key的内容'''
            parse_params_info = list(cls.dict_parse_generator(params_info))
            parse_params_info_keys=[i[0] for i in parse_params_info]
            # 将没有输出的key添加到字典
            for params_info_key in params_info:
                if params_info_key not in parse_params_info_keys:
                    parse_params_info.append([params_info_key,params_info[params_info_key]])
            for i in range(len(parse_params_info)):
                if parse_params_info[i] :
                    params_key = parse_params_info[i][:-1]
                        # 组装json提取表达式
                    params_extract_str = "']['".join(params_key)
                    params_extract_str = "['" + params_extract_str + "']"
                    params_extract_str_re = re.search("\['\d+'\]", params_extract_str)
                    if params_extract_str_re:
                        # 去除list索引下标的字符串,处理为eval能够识别的int字符串
                        params_extract_str_re = params_extract_str_re.group()
                        params_extract_str = params_extract_str.replace(params_extract_str_re,
                                            params_extract_str_re.replace("'",'').replace('"',""))
                    # 获取key内容
                    params_field_value=eval(f"params_info{params_extract_str}")
                    params_type=get_params_field_type(params_field_value=params_field_value)
                    # # 将不为空得参数值且不在枚举定义范围内的数据添加到枚举定义中,避免影响原有数据且用于完善参数覆盖情况
                    if params_field_value and (params_field_value not in cls.CONST_TYPE_ENUM[params_type]):
                        cls.CONST_TYPE_ENUM[params_type].append(params_field_value)

                    #动态执行代码:替换key的内容
                    exec(f"params_info{params_extract_str}={cls.CONST_TYPE_ENUM[params_type]}")

        def append_params_key_is_object_to_params_key_list(params_info):
            '''追加参数key对应的值是object类型的key到指定list中'''
            if isinstance(params_info,list):
                params_info=params_info[0]

            for i in params_info:
                if isinstance(params_info[i],list) and isinstance(params_info[i][0],dict)\
                        and (i not in cls.params_key_list):
                    cls.params_key_list.append(i)

        if not params_info:
            return params_info
        if isinstance(params_info, (list, dict)):
            if isinstance(params_info, list):
                if params_info:
                    params_info = params_info[0]
                cls.is_array = True
        replace_params_values(params_info)
        append_params_key_is_object_to_params_key_list(params_info)
        return params_info

    @classmethod
    def parse_uri_params_path_query(cls,uri: str, params_path: dict):
        '''解析url中的params_path与params_query参数'''
        if not params_path:
            return {},{}
        uri_split = uri.split('/')
        uri_params = [i for i in uri_split if i.startswith('{') and i.endswith('}')]
        params_path_keys = list(params_path.keys())
        uri_params_path_dict = {}  # 存储:uri中的参数是key的情况
        uri_params_query_dict = {}  # 存储:uri中的参数不是key的情况,代表是query参数
        for params_path_key in params_path_keys:
            if "{" + params_path_key + "}" in uri_params:
                uri_params_path_dict[params_path_key]=params_path[params_path_key]
            else:
                uri_params_query_dict[params_path_key]=params_path[params_path_key]
        return uri_params_path_dict,uri_params_query_dict

    @classmethod
    def join_request_uri(cls,uri,path_dict,query_dict):
        def out_path_replace_uri(uri,dict_obj):
            '''uri拼接替换后的path参数'''
            if dict_obj:
                for i in dict_obj:
                    uri = uri.replace("{" + i + "}",str(dict_obj[i]) )
                return uri
            return uri
        def out_query_replace_uri(uri,dict_obj):
            '''uri拼接替换后的query参数'''
            if dict_obj:
                uri += "?"
                for i in dict_obj:
                    uri += f"{i}={str(dict_obj[i])}&"
                uri = uri[:-1] if uri[-1] == "&" else uri
            return uri

        if not (path_dict or query_dict):
            return uri
        uri=out_path_replace_uri(uri=uri,dict_obj=path_dict)
        uri=out_query_replace_uri(uri=uri,dict_obj=query_dict)
        uri = cls.time_util.pyobject_to_json_str(uri)
        return uri

    @classmethod
    def out_target_case(cls,src_obj_index, params_all_obj):
        '''根据index返回符合条件的case'''
        if not params_all_obj:
            return {}
        _l = len(params_all_obj) - 1
        if src_obj_index > _l:
            target_case = params_all_obj[random.randint(0, _l)]
        else:
            target_case = params_all_obj[src_obj_index]
        return target_case

    @classmethod
    @exec_time_wrapper(round_num=10,module_obj=__file__,class_obj=sys._getframe().f_code.co_name,is_send_email=False)
    def generate_all_cases(cls, ordered_dict_obj,params_info):

        def convert_allpairs_cases_to_cases(params_keys,ordered_dict_obj,cases_obj):
            '''将allparis输出的case字符串转换为dict输出'''
            if len(params_keys)>=2:
                cls.time_util.append_params_key_isobject_to_extra_cases(case_params_key_obj=ordered_dict_obj,
                    params_keys=params_keys,extra_cases=cls.extra_cases,filter_func=cls.all_pairs_filter_func,
                    cases_obj=cases_obj,is_append_extra_cases=False,params_key="")
            else:
                '''params只有一个key时,直接组装字典输出(allpairs这种情况处理会输出空)'''
                cases = ordered_dict_obj
                for case in cases:
                    for case_key in cases[case]:
                        cases_obj.append({case: case_key})

        def append_extra_case_to_case(cases_obj,extra_cases,params_key_list):
            # 将extra_case数据追加到参数中
            for index,out_case in enumerate(cases_obj):
                for params_key in params_key_list:
                    update_cases=[i for i in extra_cases for o in i if o == params_key]
                    extra_case=cls.out_target_case(src_obj_index=index,params_all_obj=update_cases)
                    out_case.update(extra_case)

        def return_out_cases(params_info,ordered_dict_obj):
            '''输出最终转换完成的测试用例集合'''
            if isinstance(params_info,list):
                params_info=params_info[0]
            params_keys=[i for i in params_info]
            out_cases = []
            '''将allparis输出的case字符串转换为dict输出'''
            convert_allpairs_cases_to_cases(params_keys=params_keys,ordered_dict_obj=ordered_dict_obj,cases_obj=out_cases)
            '''将extra_case数据追加到参数中'''
            append_extra_case_to_case(cases_obj=out_cases,extra_cases=cls.extra_cases,params_key_list=cls.params_key_list)
            return out_cases

        if not (params_info or ordered_dict_obj):
            return []
        return return_out_cases(params_info=params_info,ordered_dict_obj=ordered_dict_obj)

    @classmethod
    def rm_old_excel(cls, excle_path='./', excle_name=''):
        if os.path.exists(os.path.join(excle_path, excle_name)):
            os.remove(os.path.join(excle_path, excle_name))

    @classmethod
    def reset_params_key_list_and_extra_cases(cls):
        '''每个api的参数不同,在写入后需要调用此方法重置,避免元素被重复使用'''
        cls.params_key_list=[]
        cls.extra_cases=[]
        # 还原默认的枚举定义,避免数据一直递增
        cls.CONST_TYPE_ENUM=cls.CONST_TYPE_ENUM_COPY
        cls.is_array=False

    @classmethod
    def write_params_filed_detail_to_excle(cls, params,ex_obj:operationExcle=None):
        '''将参数字段明细写入到excle'''
        ex_obj_cp=copy.deepcopy(ex_obj)
        if ex_obj is None:
            cls.rm_old_excel(excle_path=cls.excle_path, excle_name=cls.excle_name_params_field_detail)
            ex_obj = operationExcle(excle_path=cls.excle_path, excle_name=cls.excle_name_params_field_detail)
        if not isinstance(ex_obj,operationExcle):
            raise Exception(f"传入的对象预期是:{type(operationExcle)},实际为:{type(ex_obj)}")
        # print("params:",params)
        if isinstance(params,dict):
            params=[params]
        ordered_dict_obj = cls.api_prams_convert(params)
        params_all = cls.generate_all_cases(ordered_dict_obj, params)
        for case in params_all:
            for case_key in case:
                # 如果key存在与list中,说明参数是list,将object转换为array
                if case_key in cls.params_key_list:
                    case[case_key] = [case[case_key]]
            ex_obj.write_values([str(i) for i in case.values()])
        # 重置参数状态
        cls.reset_params_key_list_and_extra_cases()
        if ex_obj_cp is None:
            ex_obj.write_values(list(params_all[0].keys()))
            ex_obj.save_workbook()

    @classmethod
    def write_cases_obj_to_excle(cls, case_info, params_path,params_body,ex_obj:operationExcle=None):
        def write_cases_data_main(case_info,params_all_cases,is_body=False):
            '''
            将生成完毕的测试用例写入到excel,基础方法(将测试用例明细写入到excle)
            Args:
                case_info: 原始的测试用例信息
                params_all_cases: 使用正交生成后的所有测试用例集合
                is_body: 用于区分请求参数是否是body,如果不是bodu,则设置params_bodu为{},因为path与query类型不需要body请求,参数直接拼接到url上了
            Returns:
            '''
            for index, case in enumerate(params_all_cases):
                # print("params_all_cases:",id(params_all_cases))
                path_dict = cls.out_target_case(src_obj_index=index,
                                                params_all_obj=params_all_path) if params_all_path else {}
                query_dict = cls.out_target_case(src_obj_index=index,
                                                 params_all_obj=params_all_query) if params_all_query else {}
                # 拼接uri
                uri = cls.join_request_uri(uri=uri_copy, path_dict=path_dict, query_dict=query_dict)
                # print("path_dict:",path_dict)
                # print("query_dict:",query_dict)
                # # 忽略存在参数为空字符的uri
                # if '//' in uri:
                #     continue
                case_identifying_str = '-接口异常测试用例(基于正交实验自动生成)'
                case_name = case_info[cls.write_excle_case_field_desc['case']]
                # 拼接测试用例名称
                if case_identifying_str in case_name:
                    case_name = case_name[:case_name.find(case_identifying_str)]
                case_name = case_name + case_identifying_str + '-' + str(index + 1)
                case_info[cls.write_excle_case_field_desc['case']] = case_name
                case_info[cls.write_excle_case_field_desc['uri']] = uri

                for case_key in case:
                    # 如果key存在与list中,说明参数是list,将object转换为array
                    if case_key in cls.params_key_list:
                        case[case_key] = [case[case_key]]
                # print("case:",case)
                # 判断最外层的参数是不是list,是list,将object转换为array
                if cls.is_array:
                    case_info[cls.write_excle_case_field_desc['params_body']] = json.dumps([case], ensure_ascii=False)
                else:
                    case_info[cls.write_excle_case_field_desc['params_body']] = json.dumps(case, ensure_ascii=False)
                if not is_body:
                    # 从params_body中删除params_path&params_query对应的key
                    case_info[cls.write_excle_case_field_desc['params_body']] = json.dumps({})
                ex_obj.write_values(case_info)

        # ex_obj_cp=copy.deepcopy(ex_obj)
        if ex_obj is None:
            cls.rm_old_excel(excle_path=cls.excle_path, excle_name=cls.excle_name_params_obj)
            ex_obj = operationExcle(excle_path=cls.excle_path, excle_name=cls.excle_name_params_obj)
        if not isinstance(ex_obj,operationExcle):
            raise Exception(f"传入的对象预期是:{type(operationExcle)},实际为:{type(ex_obj)}")
        uri=case_info[cls.write_excle_case_field_desc['uri']]
        uri_copy=copy.deepcopy(uri)
        # 根据params_path对象区分uri_path参数、uri_query参数
        uri_params_path_dict,uri_params_query_dict=cls.parse_uri_params_path_query(uri=uri_copy,params_path=params_path)
        # 输出path与body的ordered_dict对象
        ordered_dict_obj_path = cls.api_prams_convert(uri_params_path_dict)
        ordered_dict_obj_query = cls.api_prams_convert(uri_params_query_dict)
        # 输出path与body所有的正交测试用例
        params_all_path = cls.generate_all_cases(ordered_dict_obj_path, uri_params_path_dict)
        params_all_query = cls.generate_all_cases(ordered_dict_obj_query, uri_params_query_dict)
        ordered_dict_obj_body = cls.api_prams_convert(params_body)
        params_all_body = cls.generate_all_cases(ordered_dict_obj_body, params_body)

        if params_all_body:
            write_cases_data_main(case_info=case_info,params_all_cases=params_all_body,is_body=True)
        elif params_all_path:
            write_cases_data_main(case_info=case_info, params_all_cases=params_all_path, is_body=False)
        elif params_all_query:
            write_cases_data_main(case_info=case_info, params_all_cases=params_all_query, is_body=False)

        # 重置参数状态
        cls.reset_params_key_list_and_extra_cases()

    @classmethod
    @exec_time_wrapper(round_num=10,module_obj=__file__,class_obj=sys._getframe().f_code.co_name,is_send_email=True)
    def batch_write_params_filed_detail_to_excle(cls,case_list=None):
        if case_list is None:
            case_list=cls.read_all_cases_data()
        cls.rm_old_excel(excle_path=cls.excle_path, excle_name=cls.excle_name_params_field_detail)
        ex_obj = operationExcle(excle_path=cls.excle_path, excle_name=cls.excle_name_params_field_detail)
        if isinstance(case_list,dict):
            case_list=[case_list]

        # 写入首行数据
        for params in case_list[1:]:
            # params是一个可变类型,程序执行中共用了此对象,这里需要传一个深拷贝对象给他,避免执行过程中params被替换
            params=copy.deepcopy(params)
            params_body=params[cls.write_excle_case_field_desc['params_body']]
            sheet_name=params[cls.write_excle_case_field_desc['case']][:31]
            sheet_name=cls.time_util.check_filename(sheet_name,priority_matching_chars=[':','/','\\','?','*','[',']'])
            # print("sheet_name:",sheet_name)
            ex_obj.create_sheet(sheet_name)
            ex_obj.data=ex_obj.get_data_for_sheet_name(sheet_name)
            if not isinstance(params_body, dict):
                params_body = json.loads(params_body)
            if isinstance(params_body,list):
                params_body=params_body[0]
            ex_obj.write_values(list(params_body.keys()))
            cls.write_params_filed_detail_to_excle(params=params_body,ex_obj=ex_obj)
        # 删除默认创建的sheet
        ex_obj.delete_sheet(sheet_name='Sheet')
        ex_obj.save_workbook()

    @classmethod
    @exec_time_wrapper(round_num=10,module_obj=__file__,class_obj=sys._getframe().f_code.co_name,is_send_email=False)
    def batch_write_cases_obj_to_excle(cls,case_info=None,case_list=None):
        if case_list is None:
            case_list=cls.read_all_cases_data()
        if isinstance(case_list, dict):
            case_list = [case_list]
        case_info_first_line=case_info
        if case_info is None:
            case_info_first_line=list(cls.write_excle_case_field_desc.keys())
            # 删除params_path, 且params_body替换为params & & response_body替换为expected
            case_info_first_line[cls.write_excle_case_field_desc['params_body']]='params'
            case_info_first_line[cls.write_excle_case_field_desc['response_body']]='expected'
        # 删除旧的文件
        cls.rm_old_excel(excle_path=cls.excle_path, excle_name=cls.excle_name_params_obj)
        ex_obj = operationExcle(excle_path=cls.excle_path, excle_name=cls.excle_name_params_obj)
        ex_obj.write_values(case_info_first_line)
        for case in case_list[1:]:
            # params是一个可变类型,程序执行中共用了此对象,这里需要传一个深拷贝对象给他,避免执行过程中params被替换
            case_info=copy.deepcopy(case)
            # if case_info[1]==:
            if case_info[1] in (
                    # '/v1/work-order/{tenantId}/{aggregateId}/repair-info',
            # # # #                 # '/v1/wx/user/logout',
            # # # #                     '/v1/wx/work-order/{tenantId}/{userId}/my-work-orders',
            # #     '/v1/work-order/tenant/{tenantId}',
                                '/v1/stakes/section/{sectionId}/number/{stakeSerialNumber}',
            # #                     '/v1/maintenance/search/select-explicit',
            # #                     '/v1/collector/find-aggregate',
                            ):
                params_body=case_info[cls.write_excle_case_field_desc['params_body']]
                params_path=case_info[cls.write_excle_case_field_desc['params_path']]
                if not isinstance(params_body,dict):
                    params_body=json.loads(params_body)
                if not isinstance(params_path,dict):
                    params_path=json.loads(params_path)
                if params_body in ({},[],[{}],None) and params_path in ({},[],[{}],None) :
                    case_info[cls.write_excle_case_field_desc['params_body']]=json.dumps(params_body)
                    case_info[cls.write_excle_case_field_desc['params_path']] = json.dumps(params_path)
                    ex_obj.write_values(case_info)
                else:
                    cls.write_cases_obj_to_excle(case_info=case_info,params_path=params_path,params_body=params_body,ex_obj=ex_obj)

        # 删除params_path对应的列
        ex_obj.del_ws_cols(cls.write_excle_case_field_desc['params_path']+1,is_save=False)
        #重命名sheet_name
        ex_obj.rename_sheet_name(src_sheet_name='Sheet',target_sheet_name='all_api_info')
        ex_obj.save_workbook()


if __name__ == "__main__":
    params = {"account": "demo", "pwd": "crmeb.com", "key": "533721295cb06314f4bcaacebc28e3bd", "code": "nbcw",
              "wxCode": "", 'userinfo': {}, 'age': 0, 'is_vip': False, 'ext': None,
              'orders': [{"order": "asc", "fileds": []}], 'orders2': [{"order2": "asc", "fileds2": []}],
              "price2":0.05,"ip":""}


    test_prams=OrderedDict([
        ('k1',[1,2,3]),
        # ('k2',[('order',[1,2,3]),('order2',[4,5,6])])
    ])




    params_array = [params]
    params_array.extend(params_array)

    #
    auto_case = autoGenrateApiCaseAllpairspy()
    path_dict = {'sectionId': 3448477344847734484773448477344847734484773448477344847734484773448477344847734484773448477344847734, 'stakeSerialNumber': '留言一点重要.文件发展就是资料论坛制作.留言一点重要.文件发展就是资料论坛制作.留言一点重要.文件发展就是资料论坛制作.留言一点重要.文件发展就是资料论坛制作.留言一点重要.文件发展就是资料论坛制作.'}
    query_dict = {"tenantId2": 22,"df":"432fsfds"}
    # url=auto_case.join_request_uri(uri="/v1/stakes/section/{sectionId}/number/{stakeSerialNumber}",path_dict=path_dict,query_dict=query_dict)
    # print(url)

    # json_str={'breakageThreshold': {}, 'breakageType': ['linear', 'alligator', 'pothole', 'raveling', 'explicit', 'subsidence', 'rut', 'seal', 'patch', 'horizontalCrack', 'verticalCrack'], 'endTime': 0, 'startTime': 0, 'tenantId': 0}
    # print(list(auto_case.dict_parse_generator(json_str)))

    # # 读取case数据
    # print(auto_case.read_all_cases_data())
    # auto_case.batch_write_cases_obj_to_excle()
    # auto_case.join_uri_params_path('/v1/stakes/section/{sectionId}/number/{stakeSerialNumber}',{"sectionId": 0, "stakeSerialNumber": "","test":123})
    # 单个写入
    # auto_case.write_params_filed_detail_to_excle(params)
    # auto_case.write_cases_obj_to_excle(case_info, params=params_array)
    # 批量写入
    # auto_case.batch_write_params_filed_detail_to_excle()
    # print("case_info:before",case_info)
    auto_case.batch_write_cases_obj_to_excle()
    # print("case_info:after",case_info)





About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK