def __init__(self): self.data = get_request_json() self.username = redis.get_username(request.headers.get('X-Token')) self.acim = ApiCompanyInfoManager() self.asim = ApiSystemInfoManager() self.aiim = ApiIntfInfoManager() self.apsrm = ApiProjectSystemRelationManager()
def __init__(self): self.data = get_request_json() self.username = redis.get_username(request.headers.get('X-Token')) self.acim = ApiCompanyInfoManager() self.asim = ApiSystemInfoManager() self.aiim = ApiIntfInfoManager() self.atim = ApiTestcaseInfoManager() self.apirm = ApiProjectIntfRelationManager() self.aidrm = ApiIntfDefaultRequestManager()
def __init__(self): self.data = get_request_json() self.username = redis.get_username(request.headers.get('X-Token')) self.atmtrm = ApiTestcaseMainTagRelationManager() self.aplm = ApiProductLineManager() self.atmm = ApiTestcaseMainManager() self.aiim = ApiIntfInfoManager() self.atsm = ApiTestcaseSubManager() self.atrqm = ApiTestcaseRequestQllManager() self.ttm = TestcaseTagManager() if self.username: self.data["userName"] = self.username
def __init__(self): self.data = get_request_json() self.username = redis.get_username(request.headers.get('X-Token')) self.acim = ApiCompanyInfoManager() self.asim = ApiSystemInfoManager() self.aiim = ApiIntfInfoManager() self.atim = ApiTestcaseInfoManager() self.atrm = ApiTestcaseRequestManager() self.attrm = ApiTestcaseTagRelationManager() self.ttm = TestcaseTagManager() self.atmm = ApiTestcaseMainManager() self.chain_list = [] self.chain_no = 0 if self.username: self.data["userName"] = self.username
def _load_main_testcase(self, testcase_main_id, testset=None, custom_flow_id=None): """ 循环加载子用例到testset """ tm_obj = atmm.get_testcase_main(id=testcase_main_id) tm_obj.testcase_name = '{0}__{1}'.format(tm_obj.testcase_name, tm_obj.expect_result) sub_list = json_loads(tm_obj.sub_list) if custom_flow_id: # 存在指定自定义链路信息,按照链路切割sub_list flow_obj = atmcfm.get_flow(id=custom_flow_id) # sub_list = sub_list[flow_obj.start_sub_index:flow_obj.start_sub_index + 1] flow_index_list = json_loads(flow_obj.flow_index_list) new_sub_list = [sub_list[i] for i in flow_index_list] sub_list = new_sub_list sub_list.reverse() # 新加载方式,耗时减少60% union_list = split_list_to_union_list(sub_list) # print(union_list) sub_objs = [] for part_list in union_list: part_sub_objs = atsm.get_testcase_subs_in_id_list(part_list) sorted_part_sub_objs = sort_objs_by_id_list(part_sub_objs, part_list) sub_objs.extend(sorted_part_sub_objs) intf_id_list = [sub_obj.api_intf_id for sub_obj in sub_objs] union_intf_id_list = split_list_to_union_list(intf_id_list) intf_objs = [] for part_list in union_intf_id_list: part_intf_objs = aiim.get_intfs_in_id_list(part_list) sorted_part_intf_objs = sort_objs_by_id_list(part_intf_objs, part_list) intf_objs.extend(sorted_part_intf_objs) for i in range(len(sub_objs)): sub_obj = sub_objs[i] print('sub_id:{}'.format(sub_obj.id)) ts_obj = sub_obj intf_obj = intf_objs[i] # print('intf_id:{}'.format(intf_obj.id)) testset = self._add_to_testset(testset, tc_obj=ts_obj, intf_obj=intf_obj, tm_obj=tm_obj) # # 旧加载方式 # for sub_id in sub_list: # print('sub_id:{}'.format(sub_id)) # ts_obj = atsm.get_testcase_sub(id=sub_id) # intf_obj = aiim.get_intf(id=ts_obj.api_intf_id) # # testset = self._add_to_testset(testset, tc_obj=ts_obj, intf_obj=intf_obj, tm_obj=tm_obj) # 接口用例(case_type==1)可能存在前置全链路用例(目前还没有) if tm_obj.case_type == 1: setup_flow_list = json_loads(tm_obj.setup_flow_list) setup_flow_list.reverse() for flow_id in setup_flow_list: testset = self._load_main_testcase(flow_id, testset=testset, custom_flow_id=custom_flow_id) return testset
def _load_api_testcase_itself(self, testcase_id, testset=None): """ 加载单个接口用例到testset """ tc_obj = atim.get_testcase(id=testcase_id) tc_obj.testcase_name = '{0}__{1}'.format(tc_obj.testcase_name, tc_obj.expect_result) intf_obj = aiim.get_intf(id=tc_obj.api_intf_id) testset = self._add_to_testset(testset, tc_obj, intf_obj) return testset
def __init__(self): self.apv = ApiPublicVariableInfoManager() self.atim = ApiTestcaseInfoManager() self.asim = ApiSystemInfoManager() self.apim = ApiProjectInfoManager() self.acim = ApiCompanyInfoManager() self.aiim = ApiIntfInfoManager() self.atmm = ApiTestcaseMainManager() self.atsm = ApiTestcaseSubManager() self.custom = read_custom() self.data = get_request_json() self.username = redis.get_username(request.headers.get('X-Token'))
def add_memo(summary): """增加一些备注,并且记录生成的公共变量""" details = summary['details'] for detail_dic in details: # 每条用例 in_out = detail_dic.pop('in_out', None) # 全链路用例增加信息 if detail_dic['is_main']: case_id = 'M' + str(detail_dic['case_id']) if 'testcase_main_id' not in summary: # summary['testcase_main_id'] = detail_dic['case_id'] testcase_main_obj = ApiTestcaseMainManager.get_testcase_main(id=detail_dic['case_id']) # summary['testcase_main_name'] = testcase_main_obj.testcase_name p_obj = ApiProductLineManager.get_product_line(id=testcase_main_obj.api_product_line_id) summary['product_line_id'] = p_obj.id summary['product_line_name'] = get_full_product_line_name(p_obj) # 接口用例增加信息 else: case_id = str(detail_dic['case_id']) if 'intf_id' not in summary: summary['intf_id'] = detail_dic['intf_id'] intf_obj = ApiIntfInfoManager.get_intf(id=detail_dic['intf_id']) summary['intf_name'] = '{0}-{1}'.format(intf_obj.intf_desc, intf_obj.intf_name) system_obj = ApiSystemInfoManager.get_system(id=intf_obj.api_system_id) summary['system_id'] = system_obj.id summary['system_name'] = system_obj.system_name # 记录随机生成的数据,方便追溯和定时清理数据 if in_out: record_keys = ['MOBILE_NO', 'ID_NO', 'BANK_CARD_NO_CREDIT', 'BANK_CARD_NO_DEBIT'] mobile_no, id_no, bank_card_no_credit, bank_card_no_debit = '', '', '', '' is_found = False for var, var_value in in_out['in'].items(): for key in record_keys: if key == var: is_found = True if var == 'MOBILE_NO': mobile_no = var_value elif var == 'ID_NO': id_no = var_value elif var == 'BANK_CARD_NO_CREDIT': bank_card_no_credit = var_value elif var == 'BANK_CARD_NO_DEBIT': bank_card_no_debit = var_value break if is_found: GenerateDataRecordManager.insert_record( case_id=case_id, mobile_no=mobile_no, id_no=id_no, bank_card_no_credit=bank_card_no_credit, bank_card_no_debit=bank_card_no_debit) return summary
def _load_api_testcase(self, testcase_id, testset=None): """ 递归加载接口用例到testset """ tc_obj = atim.get_testcase(id=testcase_id) tc_obj.testcase_name = '{0}__{1}'.format(tc_obj.testcase_name, tc_obj.expect_result) intf_obj = aiim.get_intf(id=tc_obj.api_intf_id) include_list = json_loads(tc_obj.include) setup_cases_list = include_list[1]["setup_cases"] testset = self._add_to_testset(testset, tc_obj, intf_obj) if setup_cases_list: """存在前置用例""" for setup_case_id in reversed(setup_cases_list): """前置用例id不能和自身用例id相同""" if str(setup_case_id) != str(testcase_id): """加载前置用例到testset""" testset = self._load_api_testcase(setup_case_id, testset) return testset
class ApiIntf(Resource): def __init__(self): self.data = get_request_json() self.username = redis.get_username(request.headers.get('X-Token')) self.acim = ApiCompanyInfoManager() self.asim = ApiSystemInfoManager() self.aiim = ApiIntfInfoManager() self.atim = ApiTestcaseInfoManager() self.apirm = ApiProjectIntfRelationManager() self.aidrm = ApiIntfDefaultRequestManager() @timer def post(self, action): if action == 'add': return self.add_intf() elif action == 'edit': return self.edit_intf() elif action == 'delete': return self.delete_intf() elif action == 'detail': return self.intf_detail() elif action == 'queryBySystemId': return self.query_by_system_id() else: return make_response({"code": "100", "desc": "url错误,不存在的接口动作<{action}>".format(action=action)}) @developer_check def add_intf(self): try: system_id = self.data.pop('systemId') intf_desc = self.data.pop('intfNameInChinese') intf_type = self.data.pop('type') intf_info = self.data.pop('info') request_dic = self.data.pop('request', {}) request_detail_dic = self.data.pop('requestDetail', []) intf_relation = self.data.pop('intfRelation') except KeyError: return make_response({"code": "100", "desc": "入参校验失败"}) intf_desc = str(intf_desc).strip() if not self.asim.get_system(id=system_id): return make_response({"code": "201", "desc": "工程id\"{}\"不存在".format(system_id)}) if intf_type != 'MQ': if intf_type == 'HTTP': intf_info['apiUrl'] = intf_info['apiUrl'].strip() intf_name = intf_info['apiUrl'] elif intf_type == 'DUBBO': intf_info['dubboService'] = intf_info['dubboService'].strip() intf_info['dubboMethod'] = intf_info['dubboMethod'].strip() intf_name = '{0}.{1}'.format(intf_info['dubboService'], intf_info['dubboMethod']) company_id = self.asim.get_system(id=system_id).api_company_id system_id_list = [row.id for row in self.asim.get_systems(api_company_id=company_id)] intf_name_list = [row.intf_name for row in self.aiim.get_intfs_in_system_id_list(system_id_list)] if intf_name in intf_name_list: company_name = self.acim.get_company(id=company_id).company_name return make_response({"code": "201", "desc": "\"{0}\"公司下存在相同接口\"{1}\", 请使用已存在的接口".format( company_name, intf_name)}) else: intf_info['topic'] = intf_info['topic'].strip() intf_info['tag'] = intf_info['tag'].strip() intf_name = '{0}.{1}'.format(intf_info['topic'], intf_info['tag']) obj = self.aiim.get_intf(intf_name=intf_name, api_system_id=system_id) if obj: return make_response({"code": "201", "desc": "工程下存在相同MQ接口\"{}\", 请使用已存在的MQ接口".format(intf_name)}) # 增加依赖接口列表属性 if intf_relation: intf_relation = [i[1] for i in intf_relation] self.aiim.insert_intf(intf_name=intf_name, intf_desc=intf_desc, api_system_id=system_id, intf_type=intf_type, intf_info=json_dumps(intf_info), creator=self.username, intf_relation=json_dumps(intf_relation)) else: self.aiim.insert_intf(intf_name=intf_name, intf_desc=intf_desc, api_system_id=system_id, intf_type=intf_type, intf_info=json_dumps(intf_info), creator=self.username) intf_obj = self.aiim.get_intf(intf_name=intf_name, intf_desc=intf_desc, api_system_id=system_id, intf_type=intf_type, intf_info=json_dumps(intf_info), creator=self.username) self.aidrm.insert_request(api_intf_id=intf_obj.id, request=json_dumps(request_dic), request_detail=json_dumps(request_detail_dic)) return make_response({"code": "000", "desc": "接口\"{}\"增加成功".format(intf_name)}) @developer_with_limit_check def edit_intf(self): try: intf_id = self.data.pop('intfId') intf_desc = self.data.pop('intfNameInChinese') intf_type = self.data.pop('type') intf_info = self.data.pop('info') request_dic = self.data.pop('request', {}) request_detail_dic = self.data.pop('requestDetail', []) intf_relation = self.data.pop('intfRelation') except KeyError: return make_response({"code": "100", "desc": "入参校验失败"}) intf_obj = self.aiim.get_intf(id=intf_id) if not intf_obj: return make_response({"code": "202", "desc": "接口id\"{}\"不存在, 请刷新后重试".format(intf_id)}) if intf_type != 'MQ': header_variables = [] if intf_type == 'HTTP': intf_info['apiUrl'] = intf_info['apiUrl'].strip() intf_name = intf_info['apiUrl'] header = intf_info['headers'] variable_regexp = r"\$([\w_]+)" header_variables = re.findall(variable_regexp, header) elif intf_type == 'DUBBO': intf_info['dubboService'] = intf_info['dubboService'].strip() intf_info['dubboMethod'] = intf_info['dubboMethod'].strip() intf_name = '{0}.{1}'.format(intf_info['dubboService'], intf_info['dubboMethod']) company_id = self.asim.get_system(id=intf_obj.api_system_id).api_company_id system_id_list = [row.id for row in self.asim.get_systems(api_company_id=company_id)] for obj in self.aiim.get_intfs_in_system_id_list(system_id_list): if obj.intf_name == intf_name and int(obj.id) != int(intf_id): company_name = self.acim.get_company(id=company_id).company_name return make_response({"code": "201", "desc": "\"{0}\"公司下存在相同接口\"{1}\", 无法将当前接口修改为\"{1}\"".format( company_name, intf_name)}) else: intf_info['topic'] = intf_info['topic'].strip() intf_info['tag'] = intf_info['tag'].strip() intf_name = '{0}.{1}'.format(intf_info['topic'], intf_info['tag']) obj = self.aiim.get_intf(intf_name=intf_name, api_system_id=intf_obj.api_system_id) if obj and obj.id != intf_id: return make_response({"code": "201", "desc": "工程下存在相同MQ接口\"{}\", 请使用已存在的MQ接口".format(intf_name)}) if intf_relation: intf_relation = [i[1] for i in intf_relation] self.aiim.update_intf(intf_id, intf_name=intf_name, intf_desc=intf_desc, intf_type=intf_type, intf_info=json_dumps(intf_info), last_modifier=self.username, intf_relation=json_dumps(intf_relation)) else: self.aiim.update_intf(intf_id, intf_name=intf_name, intf_desc=intf_desc, intf_type=intf_type, intf_info=json_dumps(intf_info), last_modifier=self.username) self.aidrm.update_request_by_intf_id(intf_id, request=json_dumps(request_dic), request_detail=json_dumps(request_detail_dic)) # 保存接口headers中的公共变量到接口下的所有用例 if intf_type == 'HTTP' and header_variables: to_add_pv_id_list = [] pv_objs = ApiPublicVariableInfoManager.get_variables(api_company_id=company_id) for pv_obj in pv_objs: for header_variable in header_variables: if header_variable == pv_obj.variable_name: to_add_pv_id_list.append(pv_obj.id) break # 如果存在需添加的公共变量id if to_add_pv_id_list: tc_objs = ApiTestcaseInfoManager.get_testcases(api_intf_id=intf_id) for tc_obj in tc_objs: try: pv_id_list = json_loads(tc_obj.include)[0]['public_variables'] except (json.decoder.JSONDecodeError, IndexError, KeyError): pv_id_list = [] merge_pv_id_list = pv_id_list + to_add_pv_id_list merge_pv_id_list = list(set(merge_pv_id_list)) if set(merge_pv_id_list) != set(pv_id_list): include = json_dumps([{"public_variables": merge_pv_id_list}]) ApiTestcaseInfoManager.update_testcase(id_=tc_obj.id, include=include) ts_objs = ApiTestcaseSubManager.get_testcase_subs(api_intf_id=intf_id) for ts_obj in ts_objs: try: pv_id_list = json_loads(ts_obj.include)[0]['public_variables'] except (json.decoder.JSONDecodeError, IndexError, KeyError): pv_id_list = [] merge_pv_id_list = pv_id_list + to_add_pv_id_list merge_pv_id_list = list(set(merge_pv_id_list)) if set(merge_pv_id_list) != set(pv_id_list): include = json_dumps([{"public_variables": merge_pv_id_list}]) ApiTestcaseSubManager.update_testcase_sub(id_=ts_obj.id, include=include) return make_response({"code": "000", "desc": "接口\"{}\"修改成功".format(intf_name)}) @developer_with_limit_check def delete_intf(self): try: intf_id = self.data.pop('intfId') except KeyError: return make_response({"code": "100", "desc": "入参校验失败"}) if not self.aiim.get_intf(id=intf_id): return make_response({"code": "202", "desc": "接口id\"{}\"不存在, 请刷新后重试".format(intf_id)}) testcase_objs = self.atim.get_testcases(api_intf_id=intf_id) if testcase_objs: return make_response({"code": "300", "desc": "接口下已编写{}个用例,无法直接删除".format(len(testcase_objs))}) self.aiim.delete_intf(intf_id) self.aidrm.delete_request_by_intf_id(intf_id) relation_objs = self.apirm.get_relations(api_intf_id=intf_id) for relation_obj in relation_objs: self.apirm.delete_relation(relation_obj.id) return make_response({"code": "000", "desc": "接口删除成功"}) @login_check def intf_detail(self): try: intf_id = self.data.pop('intfId') except KeyError: return make_response({"code": "100", "desc": "入参校验失败"}) intf_obj = self.aiim.get_intf(id=intf_id) if not intf_obj: return make_response({"code": "202", "desc": "接口id\"{}\"不存在, 请刷新后重试".format(intf_id)}) try: info = json.loads(intf_obj.intf_info) except json.decoder.JSONDecodeError: return make_response({"code": "301", "desc": "intf_info字段解析异常"}) intf_r_obj = self.aidrm.get_request(api_intf_id=intf_id) if intf_r_obj: request_dic = json.loads(intf_r_obj.request) request_detail_dic = json.loads(intf_r_obj.request_detail) else: request_dic = {} request_detail_dic = [] # 处理依赖列表数据 if intf_obj.intf_relation: relation_intf_objs = self.aiim.get_intfs_in_id_list(json.loads(intf_obj.intf_relation)) intf_relation = [[i.api_system_id, i.id] for i in relation_intf_objs] else: intf_relation = [] data = { 'intfChineseName': intf_obj.intf_desc, 'type': intf_obj.intf_type, 'systemId': intf_obj.api_system_id, 'info': info, 'request': request_dic, 'requestDetail': request_detail_dic, 'intfRelation': intf_relation } return make_response({"code": "000", "data": data}) @login_check def query_by_system_id(self): try: system_id = self.data.pop('systemId') project_id = self.data.pop('projectId', None) except KeyError: return make_response({"code": "100", "desc": "入参校验失败"}) all_intf_objs = self.aiim.get_intfs(api_system_id=system_id) # print(len(all_intf_objs)) all_intf_list = [] for obj in all_intf_objs: all_intf_list.append( { 'intfId': obj.id, 'label': obj.intf_name, } ) include_intf_list = [] intf_list = [] if project_id: relation_objs = self.apirm.get_relations(api_project_id=project_id) for intf_dic in all_intf_list: is_include = False for relation_obj in relation_objs: if relation_obj.api_intf_id == intf_dic['intfId']: include_intf_list.append( { 'intfId': intf_dic['intfId'], 'label': intf_dic['label'], } ) is_include = True break if not is_include: intf_list.append( { 'intfId': intf_dic['intfId'], 'label': intf_dic['label'], } ) return make_response({"code": "000", "intfList": intf_list, "includeIntfList": include_intf_list}) else: return make_response({"code": "000", "intfList": all_intf_list, "includeIntfList": include_intf_list})
class ApiTestcaseMain(Resource): def __init__(self): self.data = get_request_json() self.username = redis.get_username(request.headers.get('X-Token')) self.atmtrm = ApiTestcaseMainTagRelationManager() self.aplm = ApiProductLineManager() self.atmm = ApiTestcaseMainManager() self.aiim = ApiIntfInfoManager() self.atsm = ApiTestcaseSubManager() self.atrqm = ApiTestcaseRequestQllManager() self.ttm = TestcaseTagManager() if self.username: self.data["userName"] = self.username @timer def post(self, action): if action == 'add': return self.add_testcase_main(action) elif action == 'edit': return self.edit_testcase_main(action) elif action == 'delete': return self.delete_testcase_main() elif action == 'queryByProductLine': return self.query_by_product_line() elif action == 'queryByIntfId': return self.query_by_intf_id() elif action == 'detail': return self.testcase_detail() elif action == 'changeStatus': return self.change_status() elif action == 'copy': return self.copy_testcase() elif action == 'setTag': return self.set_tag() elif action == 'changeParent': return self.change_parent() elif action == 'queryRelatedCasesBySubId': return self.query_related_cases_by_sub_id() elif action == 'getCustomFlows': return self.get_custom_flows() elif action == 'saveCustomFlows': return self.save_custom_flows() else: return make_response({ "code": "100", "desc": "url错误,不存在的接口动作<{action}>".format(action=action) }) @developer_check def add_testcase_main(self, action): try: handle_api_testcase_main(action, **self.data) except LoadCaseError: return make_response({"code": "201", "desc": "新增用例时出错"}) return make_response({"code": "000", "desc": "用例新增成功"}) @developer_with_limit_check def edit_testcase_main(self, action): try: handle_api_testcase_main(action, **self.data) except LoadCaseError: return make_response({"code": "201", "desc": "保存用例时出错"}) return make_response({"code": "000", "desc": "用例保存成功"}) @developer_with_limit_check def delete_testcase_main(self): try: testcase_id = int(self.data.pop('testcaseId')) except KeyError: return make_response({"code": "100", "desc": CODE_DESC_MAP["100"]}) tm_obj = self.atmm.get_testcase_main(id=testcase_id) if not tm_obj: return make_response({ "code": "200", "desc": "用例id\"{}\"不存在, 请刷新后重试".format(testcase_id) }) sub_list = json_loads(tm_obj.sub_list) if tm_obj.case_type == 2: for sub_id in sub_list: sub_obj = self.atsm.get_testcase_sub(id=sub_id) main_list = json_loads( sub_obj.main_list) if sub_obj.main_list else [] if testcase_id in main_list: main_list.remove(testcase_id) self.atsm.update_testcase_sub( sub_id, main_list=json_dumps(main_list)) # self.atsm.delete_testcase_sub(sub_id) else: for sub_id in sub_list: sub_obj = self.atsm.get_testcase_sub(id=sub_id) if sub_obj.api_intf_id == tm_obj.api_intf_id: main_list = json_loads( sub_obj.main_list) if sub_obj.main_list else [] if testcase_id in main_list: main_list.remove(testcase_id) self.atsm.update_testcase_sub( sub_id, main_list=json_dumps(main_list)) # self.atsm.delete_testcase_sub(sub_id) self.atmm.delete_testcase_main(testcase_id) # 删除tag关系 relation_objs = self.atmtrm.get_relations(api_testcase_id=testcase_id) for relation_obj in relation_objs: self.atmtrm.delete_relation(relation_obj.id) return make_response({"code": "000", "desc": "测试用例删除成功"}) @login_check def query_by_product_line(self): """ 根据product_line查找该套件下的所有测试用例: 分页展示,支持用例名称搜索 """ try: product_line_id = self.data.pop('productLineId') page_no = int(self.data.pop('pageNo')) page_size = int(self.data.pop('pageSize')) testcase_name = self.data.pop('testcaseName', None) except KeyError: return make_response({"code": "100", "desc": CODE_DESC_MAP["100"]}) if not self.aplm.get_product_line(id=product_line_id): return make_response({ "code": "201", "desc": "产品线id\"{}\"不存在, 请刷新后重试".format(product_line_id) }) # 查询所有标签{类别-场景}MAP tag_base_map = self.get_tag_base_map() case_obj = self.atmm.paging_query_testcase_by_product_line_id( product_line_id, page_no, page_size, testcase_name=testcase_name) desc_list = [] for i in case_obj.items: case_status = map_number_to_case_status(i.case_status) last_run = map_number_to_last_run(i.last_run) tag_relations = self.atmtrm.get_relations(api_testcase_id=i.id) tag_map = {} for base_category in tag_base_map: tag_map[base_category] = [] for relation in tag_relations: for category, tag_list in tag_base_map.items(): for tag_dic in tag_list: if tag_dic['tagId'] == relation.tag_id: tag_map[category].append(tag_dic) testcases_dict = { "id": i.id, "testcase_name": "{0}__{1}".format(i.testcase_name, i.expect_result), "testcase_desc": i.simple_desc, "expectResult": i.expect_result, "status": case_status, "creator": username_to_nickname(i.creator), "last_modifier": username_to_nickname(i.last_modifier), "last_run": last_run, "tags": tag_map, "createTime": format(i.create_time) if i.create_time else '', "updateTime": format(i.update_time) if i.update_time else '', "lastRunTime": format(i.last_run_time) if i.last_run_time else '', } desc_list.append(testcases_dict) return make_response({ "code": "000", "desc": desc_list, "totalNum": case_obj.total }) @login_check def query_by_intf_id(self): """ 根据intf_id查找该套件下的所有测试用例: 分页展示,支持用例名称搜索 """ try: intf_id = self.data.pop('intfId') page_no = int(self.data.pop('pageNo')) page_size = int(self.data.pop('pageSize')) testcase_name = self.data.pop('testcaseName', None) except KeyError: return make_response({"code": "100", "desc": CODE_DESC_MAP["100"]}) if not self.aiim.get_intf(id=intf_id): return make_response({ "code": "201", "desc": "接口id\"{}\"不存在, 请刷新后重试".format(intf_id) }) # 查询所有标签{类别-场景}MAP tag_base_map = self.get_tag_base_map() case_obj = self.atmm.paging_query_testcase_by_intf_id( intf_id, page_no, page_size, testcase_name=testcase_name) desc_list = [] for i in case_obj.items: case_status = map_number_to_case_status(i.case_status) last_run = map_number_to_last_run(i.last_run) tag_relations = self.atmtrm.get_relations(api_testcase_id=i.id) tag_map = {} for base_category in tag_base_map: tag_map[base_category] = [] for relation in tag_relations: for category, tag_list in tag_base_map.items(): for tag_dic in tag_list: if tag_dic['tagId'] == relation.tag_id: tag_map[category].append(tag_dic) testcases_dict = { "id": i.id, "testcase_name": i.testcase_name, "testcase_desc": i.simple_desc, "expectResult": i.expect_result, "status": case_status, "creator": username_to_nickname(i.creator), "last_modifier": username_to_nickname(i.last_modifier), "last_run": last_run, "tags": tag_map, "createTime": format(i.create_time) if i.create_time else '', "updateTime": format(i.update_time) if i.update_time else '', "lastRunTime": format(i.last_run_time) if i.last_run_time else '', } desc_list.append(testcases_dict) return make_response({ "code": "000", "desc": desc_list, "totalNum": case_obj.total }) @developer_check def testcase_detail(self): try: testcase_id = self.data.pop("testcaseId") except KeyError: return make_response({"code": "100", "desc": "入参校验错误"}) tm_obj = self.atmm.get_testcase_main(id=testcase_id) if not tm_obj: return make_response({ "code": "101", "desc": "用例id\"{}\"不存在, 请刷新后重试".format(testcase_id) }) testcase_detail = get_api_testcase_main_detail(tm_obj) return make_response({"code": "000", "data": testcase_detail}) @developer_check def change_status(self): try: testcase_id = self.data.pop("id") except KeyError: return make_response({"code": "100", "desc": CODE_DESC_MAP["100"]}) obj = self.atmm.get_testcase_main(id=testcase_id) case_status = 1 if obj.case_status == 0 else 0 self.atmm.update_testcase_main(id_=testcase_id, case_status=case_status) return make_response({"code": "000", "desc": "操作成功"}) @developer_check def copy_testcase(self): try: testcase_id = self.data.pop('id') copy_num = int(self.data.pop('copyNum')) copy_type = int(self.data.pop('copyType', 1)) # 1:复制主用例,引用子用例 2:复制主用例和子用例 except (KeyError, ValueError): return make_response({"code": "100", "desc": "入参校验失败"}) tm_obj = self.atmm.get_testcase_main(id=testcase_id) if tm_obj.case_type == 2: product_line_id = tm_obj.api_product_line_id pre_obj = self.atmm.get_last_obj_by_product_line(product_line_id) else: intf_id = tm_obj.api_intf_id pre_obj = self.atmm.get_last_obj_by_intf(intf_id) index = pre_obj.index + 1 if pre_obj else 0 table_last_obj = self.atmm.get_last_obj() insert_id = table_last_obj.id + 1 if table_last_obj else 1 if copy_type == 2: from_sub_list = json_loads(tm_obj.sub_list) sub_info_list = [] for from_sub_id in from_sub_list: t_sub_obj = self.atsm.get_testcase_sub(id=from_sub_id) tr_obj = self.atrqm.get_request(api_testcase_id=from_sub_id) sub_info_list.append({ 'request': tr_obj.request, 'sub_name': t_sub_obj.sub_name, 'request_type': t_sub_obj.request_type, 'include': t_sub_obj.include, 'simple_desc': t_sub_obj.simple_desc, 'case_type': t_sub_obj.case_type, 'api_intf_id': t_sub_obj.api_intf_id, 'creator': self.username, 'expect_result': t_sub_obj.expect_result, }) testcase_insert_list = [] testcase_id_list = [] for i in range(copy_num): update_list = copy.deepcopy(sub_info_list) to_sub_list = ApiTestcaseSubManager.batch_update_testcase_sub( update_list) case_name = tm_obj.testcase_name + '_copy_{0}_{1}'.format( testcase_id, i + 1) testcase_insert_list.append({ 'id': insert_id + i, 'testcase_name': case_name, 'simple_desc': tm_obj.simple_desc, 'case_type': tm_obj.case_type, 'case_status': tm_obj.case_status, 'api_intf_id': tm_obj.api_intf_id, 'api_product_line_id': tm_obj.api_product_line_id, 'sub_list': json_dumps(to_sub_list), 'creator': self.username, 'expect_result': tm_obj.expect_result, 'index': index + i, 'setup_flow_list': tm_obj.setup_flow_list, 'main_teardown_hooks': tm_obj.main_teardown_hooks, }) testcase_id_list.append(insert_id + i) self.atmm.batch_insert_testcase_main(testcase_insert_list) # 复制tag tag_relation_objs = self.atmtrm.get_relations( api_testcase_id=testcase_id) tag_id_list = [str(obj.tag_id) for obj in tag_relation_objs] tag_relation_insert_list = [] for i in range(copy_num): for tag_id in tag_id_list: tag_relation_insert_list.append({ 'api_testcase_id': testcase_id_list[i], 'tag_id': tag_id }) self.atmtrm.batch_insert_relation(tag_relation_insert_list) elif copy_type == 1: to_sub_list = json_loads(tm_obj.sub_list) testcase_insert_list = [] testcase_id_list = [] for i in range(copy_num): case_name = tm_obj.testcase_name + '_copy_{0}_{1}'.format( testcase_id, i + 1) testcase_insert_list.append({ 'id': insert_id + i, 'testcase_name': case_name, 'simple_desc': tm_obj.simple_desc, 'case_type': tm_obj.case_type, 'case_status': tm_obj.case_status, 'api_intf_id': tm_obj.api_intf_id, 'api_product_line_id': tm_obj.api_product_line_id, 'sub_list': json_dumps(to_sub_list), 'creator': self.username, 'expect_result': tm_obj.expect_result, 'index': index + i, 'setup_flow_list': tm_obj.setup_flow_list, 'main_teardown_hooks': tm_obj.main_teardown_hooks, }) testcase_id_list.append(insert_id + i) self.atmm.batch_insert_testcase_main(testcase_insert_list) # 复制tag tag_relation_objs = self.atmtrm.get_relations( api_testcase_id=testcase_id) tag_id_list = [str(obj.tag_id) for obj in tag_relation_objs] tag_relation_insert_list = [] for i in range(copy_num): for tag_id in tag_id_list: tag_relation_insert_list.append({ 'api_testcase_id': testcase_id_list[i], 'tag_id': tag_id }) self.atmtrm.batch_insert_relation(tag_relation_insert_list) else: return make_response({ "code": "101", "desc": "错误的copy_type:{0}".format(copy_type) }) return make_response({ "code": "000", "desc": "用例{0}复制成功, 数量{1}".format(testcase_id, copy_num) }) @developer_with_limit_check def set_tag(self): try: testcase_id = self.data.pop("testcaseId") tag_id_list = self.data.pop("tagIdList") except KeyError: return make_response({"code": "100", "desc": "入参校验错误"}) for tag_id in tag_id_list: if not self.ttm.get_testcase_tag(tag_id): return make_response({ "code": "200", "desc": "标签id\"{}\"不存在, 请刷新后重试".format(tag_id) }) set_testcase_tag(testcase_id, tag_id_list, is_main=True) return make_response({"code": "000", "desc": "设置标签成功"}) @login_check def query_related_cases_by_sub_id(self): try: sub_id = self.data.pop("subId") except KeyError: return make_response({"code": "100", "desc": "入参校验错误"}) sub_obj = ApiTestcaseSubManager.get_testcase_sub(id=sub_id) if not sub_obj or not sub_obj.main_list or not json_loads( sub_obj.main_list): return make_response({"code": "101", "desc": "没有关联的用例信息"}) main_id_list = json_loads(sub_obj.main_list) main_objs = ApiTestcaseMainManager.get_testcases_in_id_list( main_id_list) data_list = [] for main_obj in main_objs: p_obj = ApiProductLineManager.get_product_line( id=main_obj.api_product_line_id) data_dic = { "testcaseId": main_obj.id, "testcaseName": main_obj.testcase_name, "productLineDesc": get_full_product_line_name(p_obj) } data_list.append(data_dic) return make_response({"code": "000", "data": data_list}) @login_check def get_custom_flows(self): try: testcase_id = self.data.pop('testcaseId') except KeyError: return make_response({"code": "100", "desc": CODE_DESC_MAP["100"]}) flow_objs = ApiTestcaseMainCustomFlowManager.get_flows( testcase_id=testcase_id) data_list = [{ 'flowId': obj.id, 'flowName': obj.flow_name, 'flowIndexList': json_loads(obj.flow_index_list) } for obj in flow_objs] return make_response({"code": "000", "flowList": data_list}) @developer_check def save_custom_flows(self): try: testcase_id = self.data.pop('testcaseId') flow_list = self.data.pop('flowList') except KeyError: return make_response({"code": "100", "desc": CODE_DESC_MAP["100"]}) save_flow(testcase_id, flow_list) return make_response({"code": "000", "desc": "保存成功"}) @developer_check def change_parent(self): try: testcase_id = self.data.pop('testcaseId') parent_id = self.data.pop('newParentId') except KeyError: return make_response({"code": "100", "desc": CODE_DESC_MAP["100"]}) tm_obj = self.atmm.get_testcase_main(id=testcase_id) if tm_obj.case_type == 2: pl_obj = self.aplm.get_product_line(id=parent_id) if not pl_obj: return make_response({ "code": "202", "desc": "不存在的目录id, 请刷新后重试" }) sub_obj = self.aplm.get_product_line(parent_id=pl_obj.id) if sub_obj: return make_response({ "code": "500", "desc": "移动失败,新目录下包含其他目录,请移动到最后一层目录中" }) pre_tm_obj = self.atmm.get_last_obj_by_product_line(parent_id) else: intf_obj = self.aiim.get_intf(id=parent_id) if not intf_obj: return make_response({ "code": "201", "desc": "不存在的接口id, 请刷新后重试" }) pre_tm_obj = self.atmm.get_last_obj_by_intf(parent_id) # 更新原产品线/原接口其他用例的index self.atmm.index_update_while_remove_testcase(id_=testcase_id) # 获取新产品线/新接口的用例index index = pre_tm_obj.index + 1 if pre_tm_obj else 0 # 更新 if tm_obj.case_type == 2: self.atmm.update_testcase_main(id_=testcase_id, api_product_line_id=parent_id, index=index) else: self.atmm.update_testcase_main(id_=testcase_id, api_intf_id=parent_id, index=index) return make_response({"code": "000", "desc": "移动成功"}) def get_tag_base_map(self): # 查询所有标签{类别-场景}MAP tag_objs = self.ttm.query_testcase_tag() tag_base_map = {} for tag_obj in tag_objs: if tag_obj.tag_category not in tag_base_map: tag_base_map[tag_obj.tag_category] = [{ "tagId": tag_obj.id, "tagName": tag_obj.tag_name }] else: tag_base_map[tag_obj.tag_category].append({ "tagId": tag_obj.id, "tagName": tag_obj.tag_name }) return tag_base_map
class ApiSystem(Resource): def __init__(self): self.data = get_request_json() self.username = redis.get_username(request.headers.get('X-Token')) self.acim = ApiCompanyInfoManager() self.asim = ApiSystemInfoManager() self.aiim = ApiIntfInfoManager() self.apsrm = ApiProjectSystemRelationManager() @timer def post(self, action): if action == 'add': return self.add_system() elif action == 'edit': return self.edit_system() elif action == 'delete': return self.delete_system() elif action == 'queryByCompanyId': return self.query_by_company_id() elif action == 'getGitBranchNamesBySystemId': return self.get_git_branch_names_by_system_id() else: return make_response({ "code": "100", "desc": "url错误,不存在的接口动作<{action}>".format(action=action) }) @master_check def add_system(self): try: company_id = self.data.pop('companyId') system_name = self.data.pop('systemName') git_ssh_url = self.data.pop('gitSshURL') simple_desc = self.data.pop('simpleDesc', None) except KeyError: return make_response({"code": "100", "desc": "入参校验失败"}) system_name = str(system_name).strip() git_ssh_url = str(git_ssh_url).strip() if not self.acim.get_company(id=company_id): return make_response({ "code": "201", "desc": "公司id\"{}\"不存在".format(company_id) }) if self.asim.get_system(system_name=system_name, api_company_id=company_id): return make_response({ "code": "201", "desc": "公司下存在相同工程名称\"{}\", 无法新增".format(system_name) }) self.asim.insert_system(system_name=system_name, simple_desc=simple_desc, api_company_id=company_id, git_url=git_ssh_url, creator=self.username) return make_response({ "code": "000", "desc": "工程\"{}\"增加成功".format(system_name) }) @master_check def edit_system(self): try: system_id = self.data.pop('systemId') system_name = self.data.pop('systemName') git_ssh_url = self.data.pop('gitSshURL') simple_desc = self.data.pop('simpleDesc', None) except KeyError: return make_response({"code": "100", "desc": "入参校验失败"}) system_obj = self.asim.get_system(id=system_id) if not system_obj: return make_response({ "code": "202", "desc": "工程id\"{}\"不存在, 请刷新后重试".format(system_id) }) exist_system_obj = self.asim.get_system( system_name=system_name, api_company_id=system_obj.api_company_id) if exist_system_obj and exist_system_obj.id != int(system_id): return make_response({ "code": "201", "desc": "公司下存在相同工程名称\"{}\", 无法修改".format(system_name) }) self.asim.update_system(system_id, system_name=system_name, git_url=git_ssh_url, simple_desc=simple_desc, last_modifier=self.username) return make_response({ "code": "000", "desc": "工程\"{}\"修改成功".format(system_name) }) @master_check def delete_system(self): try: system_id = self.data.pop('systemId') except KeyError: return make_response({"code": "100", "desc": "入参校验失败"}) if not self.asim.get_system(id=system_id): return make_response({ "code": "202", "desc": "工程id\"{}\"不存在, 请刷新后重试".format(system_id) }) intf_objs = self.aiim.get_intfs(api_system_id=system_id) if intf_objs: return make_response({ "code": "300", "desc": "工程下已配置{}个接口,无法直接删除".format(len(intf_objs)) }) self.asim.delete_system(system_id) return make_response({"code": "000", "desc": "工程删除成功"}) # @login_check def query_by_company_id(self): try: company_id = self.data.pop('companyId') project_id = self.data.pop('projectId', None) except KeyError: return make_response({"code": "100", "desc": "入参校验失败"}) all_system_objs = self.asim.get_systems(api_company_id=company_id) all_system_list = [] for obj in all_system_objs: all_system_list.append({ 'systemId': obj.id, 'label': obj.system_name, 'gitUrl': obj.git_url }) include_system_list = [] system_list = [] if project_id: relation_objs = self.apsrm.get_relations(api_project_id=project_id) for system_dic in all_system_list: is_include = False for relation_obj in relation_objs: if relation_obj.api_system_id == system_dic['systemId']: include_system_list.append({ 'systemId': system_dic['systemId'], 'label': system_dic['label'], }) is_include = True break if not is_include: system_list.append({ 'systemId': system_dic['systemId'], 'label': system_dic['label'], }) return make_response({ "code": "000", "systemList": system_list, "includeSystemList": include_system_list }) else: return make_response({ "code": "000", "allSystemList": all_system_list }) def get_git_branch_names_by_system_id(self): try: git_url = self.data.pop('gitUrl') except KeyError: return make_response({"code": "100", "desc": "入参校验失败"}) git_userspace_name = git_url.split(":")[1].strip('.git') try: git = GitlabAPI() git_branches_list = git.get_project_branches(git_userspace_name) return make_response({ "code": "000", "data": { "gitUrl": git_url, "gitBranchList": git_branches_list } }) except: return make_response({"code": "999", "desc": "系统内部错误"})
def get_testcase_chain(testcase_id, case_type, chain_list=None, with_intf_system_name=None, with_extract=None, only_first=False, main_case_flow_id=None, childless=False): """ 根据testcase_id获取调用链, 包含接口用例和全链路用例 return example: [ { "preCaseId": 1, "preCaseName": "指定手机获取验证码", "preCaseType": "接口用例", "preIntfName": "接口描述-/url/api" }, { "preCaseId": 27, "preCaseName": "新户申请钱包", "preCaseType": "全链路用例" }, { "preCaseId": 2, "preCaseName": "登录", "preCaseType": "接口用例" } ] """ if not chain_list: chain_list = [] # 调用链最大长度保护 if len(chain_list) >= 100: return chain_list if case_type == 1: tc_obj = ApiTestcaseInfoManager.get_testcase(id=testcase_id) if tc_obj: if with_intf_system_name: intf_obj = ApiIntfInfoManager.get_intf(id=tc_obj.api_intf_id) system_obj = ApiSystemInfoManager.get_system( id=intf_obj.api_system_id) chain_row_dic = { "preCaseName": '{0}__{1}'.format(tc_obj.testcase_name, tc_obj.expect_result), "preCaseId": tc_obj.id, "preCaseType": get_desc_by_case_type(case_type), "preIntfName": '{0}-{1}'.format(intf_obj.intf_desc, intf_obj.intf_name), "preSystemName": system_obj.system_name } if with_extract: # 解析出用例中提取变量 extract_v_names = get_extract_v_names(testcase_id) public_v_names = get_public_v_names(tc_obj) chain_row_dic.update({ "extract_v_names": extract_v_names, "public_v_names": public_v_names }) chain_list.insert(0, chain_row_dic) else: chain_row_dic = { "preCaseName": '{0}__{1}'.format(tc_obj.testcase_name, tc_obj.expect_result), "preCaseId": tc_obj.id, "preCaseType": get_desc_by_case_type(case_type), } if with_extract: # 解析出用例中提取变量 extract_v_names = get_extract_v_names(testcase_id) public_v_names = get_public_v_names(tc_obj) chain_row_dic.update({ "extract_v_names": extract_v_names, "public_v_names": public_v_names }) chain_list.insert(0, chain_row_dic) if childless: chain_list[0]['hasChildren'] = False return chain_list setup_case_list = json.loads( tc_obj.setup_case_list) if tc_obj.setup_case_list else [] setup_case_list.reverse() if setup_case_list: if only_first: chain_list[0]['hasChildren'] = True return chain_list else: # 继续递归查询前置 for setup_case_str in setup_case_list: setup_case_type, setup_case_id, option = parse_setup_case_str( setup_case_str) kwargs = { 'chain_list': chain_list, 'with_intf_system_name': with_intf_system_name, 'with_extract': with_extract } if setup_case_type == 1: if option == 'self': kwargs['childless'] = True elif setup_case_type == 2: kwargs['main_case_flow_id'] = option chain_list = get_testcase_chain( setup_case_id, setup_case_type, **kwargs) # setup_case_type, setup_case_id, setup_case_flow_id = parse_setup_case_str(setup_case_str) # chain_list = get_testcase_chain( # setup_case_id, setup_case_type, chain_list=chain_list, # with_intf_system_name=with_intf_system_name, with_extract=with_extract, # main_case_flow_id=setup_case_flow_id # ) else: if only_first: chain_list[0]['hasChildren'] = False return chain_list return chain_list elif case_type == 2: tm_obj = ApiTestcaseMainManager.get_testcase_main(id=testcase_id) if tm_obj: chain_list.insert( 0, { "preCaseName": '{0}__{1}'.format(tm_obj.testcase_name, tm_obj.expect_result), "preCaseId": tm_obj.id, "preCaseType": get_desc_by_case_type(case_type), "preIntfName": '', "preSystemName": '', "customFlowId": None, "customFlowName": '' }) if only_first: chain_list[0]['hasChildren'] = False if main_case_flow_id: flow_obj = ApiTestcaseMainCustomFlowManager.get_flow( id=main_case_flow_id) if flow_obj: chain_list[0]['customFlowName'] = flow_obj.flow_name chain_list[0]['customFlowId'] = flow_obj.id return chain_list
def get_api_testcase_main_detail(tm_obj): """ 新版-获取主测试用例详情 :param tm_obj: :return: """ custom = read_custom() pvim = ApiPublicVariableInfoManager() public_v_objs = pvim.get_variables() case_type = tm_obj.case_type main_teardown_info = [] if tm_obj.main_teardown_hooks: main_teardown_hooks = json.loads(tm_obj.main_teardown_hooks) for teardown in main_teardown_hooks: teardown = teardown.replace("||$DB_CONNECT", "", 1).replace("||$DISCONF_HOST", "", 1) teardown_func_name = teardown.split("${")[1].split("(")[0] teardown_func_args = teardown[:-2].split("(", 1)[-1] for teardown_hook in custom["teardown-hooks"]: if teardown_hook["name"] == teardown_func_name: args_dict = {} for a, p in zip(teardown_func_args.split('||'), teardown_hook["parameters"]): args_dict[p] = a main_teardown_info.append({ "name": teardown_func_name, "desc": teardown_hook["description"], "args": args_dict }) # # 返回自定义flow信息 # custom_flow_objs = ApiTestcaseMainCustomFlowManager.get_flows(testcase_id=tm_obj.id) # custom_flow_list = [ # { # "flowId": obj.id, # "flowName": obj.flow_name, # "startEnd": [obj.start_sub_index, obj.end_sub_index] # } # for obj in custom_flow_objs # ] response = { "base": { "testcaseName": tm_obj.testcase_name, "testcaseDesc": tm_obj.simple_desc if tm_obj.simple_desc else '', "creator": tm_obj.creator, "last_modifier": tm_obj.last_modifier, "expectResult": tm_obj.expect_result if tm_obj.expect_result else '', "mainTeardownInfo": main_teardown_info, }, "steps": [], } _all_main_case_objs = None if case_type == 1: response["base"].update({ "caseType": case_type, "intfId": tm_obj.api_intf_id, }) response["setupFlow"] = [] setup_flow_id_list = json.loads(tm_obj.setup_flow_list) for setup_flow_id in setup_flow_id_list: flow_obj = ApiTestcaseMainManager.get_testcase_main( id=setup_flow_id) pl_obj = ApiProductLineManager.get_product_line( id=flow_obj.api_product_line_id) product_line_name = pl_obj.product_line_name if pl_obj else "" response["setupFlow"].append({ "flowCaseId": setup_flow_id, "flowName": flow_obj.testcase_name, "productLineName": product_line_name, "productLineId": flow_obj.api_product_line_id, }) _all_main_case_objs = ApiTestcaseMainManager.get_testcase_mains() sub_id_list = json.loads(tm_obj.sub_list) ts_objs = ApiTestcaseSubManager.get_testcase_subs_in_id_list(sub_id_list) tr_objs = ApiTestcaseRequestQllManager.get_requests_in_case_id_list( sub_id_list) intf_id_list = [ts_obj.api_intf_id for ts_obj in ts_objs] intf_objs = ApiIntfInfoManager.get_intfs_in_id_list(intf_id_list) for sub_id in sub_id_list: sub_dic = { "base": {}, "setupInfo": [], "teardownInfo": [], "requestTeardownInfo": [], "requestInfo": {}, "validateInfo": [], "extractInfo": [], "variableInfo": [] } # ts_obj = ApiTestcaseSubManager.get_testcase_sub(id=sub_id) # tr_obj = ApiTestcaseRequestQllManager.get_request(api_testcase_id=sub_id) # intf_obj = ApiIntfInfoManager.get_intf(id=ts_obj.api_intf_id) ts_obj = None tr_obj = None intf_obj = None for obj in ts_objs: if obj.id == sub_id: ts_obj = obj break for obj in tr_objs: if obj.api_testcase_id == sub_id: tr_obj = obj break if not ts_obj or not tr_obj: continue for obj in intf_objs: if obj.id == ts_obj.api_intf_id: intf_obj = obj break request = tr_obj.request include = ts_obj.include request_type = ts_obj.request_type # 返回base sub_dic["base"]["intfId"] = ts_obj.api_intf_id sub_dic["base"]["intfName"] = intf_obj.intf_name sub_dic["base"][ "intfNameInChinese"] = intf_obj.intf_desc if intf_obj.intf_desc else '' sub_dic["base"]["subId"] = sub_id sub_dic["base"]["subName"] = ts_obj.sub_name sub_dic["base"][ "subDesc"] = ts_obj.simple_desc if ts_obj.simple_desc else '' sub_dic["base"][ "subExpectResult"] = ts_obj.expect_result if ts_obj.expect_result else '' sub_dic["base"][ "isMultiQuote"] = True if ts_obj.main_list and json.loads( ts_obj.main_list) and len(json.loads( ts_obj.main_list)) > 1 else False sub_dic["base"]["requestType"] = map_number_to_testcase_type( request_type) if case_type == 1: sub_dic["base"][ "isSelf"] = True if ts_obj.api_intf_id == tm_obj.api_intf_id else False # testcase_request = json.loads(request.replace("'", "\"")) testcase_request = json.loads(request) last_teststeps = len(testcase_request["teststeps"]) - 1 # 返回variableInfo for variable in testcase_request["teststeps"][last_teststeps][ "variables"]: for variable_key, variable_value in variable.items(): if 1 == 0: pass else: variable_dict = {} # variable_value = str(variable_value) save_as_type = get_save_as_type(variable_value) variable_value = str(variable_value) # 自定义变量-db if variable_value.startswith("${variable_db_operation("): variable_dict["name"] = variable_key variable_dict["type"] = "db" variable_dict["value"] = variable_value.replace( "${variable_db_operation(", "", 1).replace("||$DB_CONNECT)}", "", 1) # 变量类型-function elif variable_value.startswith( '${') and variable_value.endswith('}'): func_name = variable_value.split('${')[-1].split( '(')[0] if 'variable_db_operation' == func_name: continue args_list = variable_value[:-2].split( '(', 1)[-1].split('||') args_dict = {} for func in custom["functions"]: if func["name"] == func_name: for a, p in zip(args_list, func["parameters"]): args_dict[p] = a break variable_dict["name"] = variable_key variable_dict["type"] = "function" variable_dict["value"] = func_name variable_dict["args"] = args_dict # 变量类型-constant else: variable_dict["saveAs"] = save_as_type variable_dict["name"] = variable_key variable_dict["type"] = "constant" variable_dict["value"] = variable_value sub_dic["variableInfo"].append(variable_dict) # 返回setupInfo testcase_setup_hooks = testcase_request["teststeps"][last_teststeps][ "setup_hooks"] for setup in testcase_setup_hooks: setup_func_name = setup.split("${")[1].split("(")[0] setup_func_args = setup[:-2].split("(", 1)[-1] # setup_func_args = re.findall(r'[^()]+', setup.split("{")[-1].split('}')[0])[1] # setup_func_args = re.findall(r'[(](.*?)[)]', setup,re.S)[0] '''判断request字段里面的setup_hooks里面是否有前置操作,有则返回至detail的setupInfo''' for setup_hook in custom["setup-hooks"]: if setup_hook["name"] == setup_func_name: if setup_func_name == "setup_db_operation": sub_dic["setupInfo"].append({ "name": setup_func_name, "desc": setup_hook["description"], "args": { "sql": setup_func_args.replace( "||$DB_CONNECT", "", 1) } }) elif setup_func_name == "setup_wait_until_db_result_succeed": args_dict = {} for a, p in zip(setup_func_args.split('||'), setup_hook["parameters"]): if p == "sql": args_dict[p] = a.replace( "||$DB_CONNECT", "", 1) else: args_dict[p] = a sub_dic["setupInfo"].append({ "name": setup_func_name, "desc": setup_hook["description"], "args": args_dict }) else: ''' # { # "name": "execution_testcase", # "args": { # "用例编号": "4173", # "请求参数": "{\"phone\":\"18260037329\"}" # } # } # ''' args_dict = {} for a, p in zip(setup_func_args.split('||'), setup_hook["parameters"]): args_dict[p] = a sub_dic["setupInfo"].append({ "name": setup_func_name, "desc": setup_hook["description"], "args": args_dict }) '''判断request字段里面的setup_hooks里面是否有加签函数,有则返回至detail的requestInfo''' for setup_hook in custom["sign"]: if setup_hook["name"] == setup_func_name: if "sign" in setup_func_name: '''setup_hooks中是否有加签函数''' sub_dic["requestInfo"]["sign"] = { "name": setup_func_name, "desc": setup_hook["description"] } # 返回teardownInfo testcase_teardown_hooks = testcase_request["teststeps"][ last_teststeps]["teardown_hooks"] for teardown in testcase_teardown_hooks: teardown_func_name = teardown.split("${")[1].split("(")[0] teardown_func_args = teardown[:-2].split("(", 1)[-1] for teardown_hook in custom["teardown-hooks"]: if teardown_hook["name"] == teardown_func_name: if teardown_func_name == "teardown_db_operation": sub_dic["teardownInfo"].append({ "name": teardown_func_name, "desc": teardown_hook["description"], "args": { "sql": teardown_func_args.replace( "||$DB_CONNECT", "", 1) } }) elif teardown_func_name == "teardown_wait_until_db_result_succeed": args_dict = {} for a, p in zip(teardown_func_args.split('||'), teardown_hook["parameters"]): if p == "sql": args_dict[p] = a.replace( "||$DB_CONNECT", "", 1) else: args_dict[p] = a sub_dic["teardownInfo"].append({ "name": teardown_func_name, "desc": teardown_hook["description"], "args": args_dict }) else: """如果args是列表,返回args列表""" args_dict = {} for a, p in zip(teardown_func_args.split('||'), teardown_hook["parameters"]): args_dict[p] = a sub_dic["teardownInfo"].append({ "name": teardown_func_name, "desc": teardown_hook["description"], "args": args_dict }) # 返回requestTeardownInfo request_teardown_hooks = testcase_request["teststeps"][ last_teststeps].get("request_teardown_hooks", []) for teardown in request_teardown_hooks: teardown_func_name = teardown.split("${")[1].split("(")[0] teardown_func_args = teardown[:-2].split("(", 1)[-1] for teardown_hook in custom["teardown-hooks"]: if teardown_hook["name"] == teardown_func_name: """如果args是列表,返回args列表""" args_dict = {} for a, p in zip(teardown_func_args.split('||'), teardown_hook["parameters"]): args_dict[p] = a sub_dic["requestTeardownInfo"].append({ "name": teardown_func_name, "desc": teardown_hook["description"], "args": args_dict }) # 返回requestInfo[json] requests_dict = testcase_request["teststeps"][last_teststeps][ "request"] is_merge = requests_dict.pop("isMerge", True) if request_type == 1: for json_value in requests_dict.values(): sub_dic["requestInfo"]["json"] = json_value # 增加入参校验 include_li = json.loads(include) if len(include_li) >= 3: param_check_dic = include_li[2]["param_check"] for item, p_list in param_check_dic.items(): if item == 'empty': sub_dic["requestInfo"]["emptyCheckParamList"] = p_list elif request_type == 2: for args_value in requests_dict.values(): sub_dic["requestInfo"] = args_value elif request_type == 3: for msg_value in requests_dict.values(): sub_dic["requestInfo"] = msg_value sub_dic["requestInfo"]["isMerge"] = is_merge sub_dic["requestInfo"]["type"] = request_type # 返回extractInfo for extract in testcase_request["teststeps"][last_teststeps][ "extract"]: for extract_key, extract_value in extract.items(): sub_dic["extractInfo"].append({ "saveAs": extract_key, "check": extract_value }) # 返回validateInfo for validate in testcase_request["teststeps"][last_teststeps][ "validate"]: for comparator, veirfy in validate.items(): if comparator == 'db_validate' and veirfy[0].endswith( '$DB_CONNECT'): veirfy[0] = veirfy[0].split("$DB_")[0] sub_dic["validateInfo"].append({ "comparator": comparator, "desc": comparator, "check": veirfy[0], "expect": veirfy[1], "comment": veirfy[2] if len(veirfy) >= 3 else '', }) # 返回include if not (include is None or len(include) < 3): testcase_include = json.loads(include) include_list = [{"public_variables": []}] for pv_id in testcase_include[0]["public_variables"]: # obj = pvim.get_variable(id=pv_id) obj = None for public_v_obj in public_v_objs: if public_v_obj.id == pv_id: obj = public_v_obj break if not obj: continue id_, name, type_name, desc = obj.id, obj.variable_name, obj.type, obj.simple_desc value = [v.strip() for v in obj.value.strip('##').split('##')][0] include_list[0]["public_variables"].append({ "id": id_, "name": name, "value": value, "type": type_name, "desc": desc }) sub_dic["include"] = include_list # 返回relatedMainCases if case_type == 1: sub_dic.update({"relatedCases": []}) for main_case_obj in _all_main_case_objs: if main_case_obj.case_type == 2: continue other_case_sub_list = json.loads(main_case_obj.sub_list) if sub_id in other_case_sub_list: sub_dic["relatedCases"].append({ "testcaseId": main_case_obj.id, "testcaseName": main_case_obj.testcase_name }) response["steps"].append(sub_dic) return response
class ApiTestcase(Resource): def __init__(self): self.data = get_request_json() self.username = redis.get_username(request.headers.get('X-Token')) self.acim = ApiCompanyInfoManager() self.asim = ApiSystemInfoManager() self.aiim = ApiIntfInfoManager() self.atim = ApiTestcaseInfoManager() self.atrm = ApiTestcaseRequestManager() self.attrm = ApiTestcaseTagRelationManager() self.ttm = TestcaseTagManager() self.atmm = ApiTestcaseMainManager() self.chain_list = [] self.chain_no = 0 if self.username: self.data["userName"] = self.username # self.USERNAME_NICKNAME_DIC = {row[0]: row[1] for row in UserManager.get_all_username_nickname()} @staticmethod def username2nickname_fast(username): if not username: return username cache = CacheData() if username in cache.USERNAME_NICKNAME_DIC: return cache.USERNAME_NICKNAME_DIC[username] else: return username @timer def post(self, action): if action == 'add': return self.add_testcase(action) elif action == 'edit': return self.edit_testcase(action) elif action == 'delete': return self.delete_testcase() # elif action == 'detailOld': # return self.testcase_detail_old() elif action == 'detail': return self.testcase_detail() elif action == 'queryByIntfId': return self.query_by_intf_id() elif action == 'changeStatus': return self.change_status() elif action == 'copy': return self.copy_testcase() elif action == 'copyBytestcaseData': return self.copy_testcase_data() elif action == 'queryByCallchain': return self.query_callchain() elif action == 'setTag': return self.set_tag() elif action == 'changeParent': return self.change_parent() elif action == 'detailWithSetup': return self.testcase_detail_with_setup() elif action == 'queryListBySetupCase': return self.query_list_by_setup_case() else: return make_response({ "code": "100", "desc": "url错误,不存在的接口动作<{action}>".format(action=action) }) @developer_check def add_testcase(self, action): try: handle_api_testcase(action, **self.data) except LoadCaseError: return make_response({"code": "200", "desc": "新增用例时出错"}) return make_response({"code": "000", "desc": "用例新增成功"}) @developer_with_limit_check def edit_testcase(self, action): try: handle_api_testcase(action, **self.data) except LoadCaseError: return make_response({"code": "200", "desc": "编辑用例时出错"}) return make_response({"code": "000", "desc": "用例修改成功"}) @developer_with_limit_check def delete_testcase(self): try: testcase_id = self.data.pop('testcaseId') except KeyError: return make_response({"code": "100", "desc": "入参校验失败"}) if not self.atim.get_testcase(id=testcase_id): return make_response({ "code": "200", "desc": "用例id\"{}\"不存在, 请刷新后重试".format(testcase_id) }) # 检查当前用例是否被其他用例作为前置,如果是无法删除 setup_case_lists = self.atim.get_id_and_setup_case_list() is_setupped = False for setup_case_list in setup_case_lists: if is_setupped: break if setup_case_list[1]: setup_cases = eval(setup_case_list[1]) for setup_case_id in setup_cases: if int(setup_case_id.split('-')[1]) == testcase_id: is_setupped = True break if is_setupped: return make_response({ "code": "300", "desc": "当前用例被其他用例引用为前置,无法直接删除" }) self.atim.delete_testcase(testcase_id) r_obj = self.atrm.get_request(api_testcase_id=testcase_id) if r_obj: self.atrm.delete_request(r_obj.id) # 删除tag关系 relation_objs = ApiTestcaseTagRelationManager.get_relations( api_testcase_id=testcase_id) for relation_obj in relation_objs: ApiTestcaseTagRelationManager.delete_relation(relation_obj.id) return make_response({"code": "000", "desc": "测试用例删除成功"}) @developer_check def testcase_detail(self): try: testcase_id = self.data.pop("testcaseId") except KeyError: return make_response({"code": "100", "desc": "入参校验错误"}) tc_obj = self.atim.get_testcase(id=testcase_id) if not tc_obj: return make_response({ "code": "101", "desc": "用例id\"{}\"不存在, 请刷新后重试".format(testcase_id) }) testcase_detail = get_api_testcase_detail(tc_obj) return make_response({"code": "000", "data": testcase_detail}) @login_check def query_by_intf_id(self): """ 根据intf_id查找该套件下的所有测试用例: 分页展示,支持用例名称搜索 """ try: intf_id = self.data.pop('intfId') page_no = int(self.data.pop('pageNo')) page_size = int(self.data.pop('pageSize')) testcase_name = self.data.pop('testcaseName', None) except KeyError: return make_response({"code": "100", "desc": "入参校验失败"}) if not self.aiim.get_intf(id=intf_id): return make_response({ "code": "201", "desc": "接口id\"{}\"不存在, 请刷新后重试".format(intf_id) }) # 查询所有标签{类别-场景}MAP tag_objs = self.ttm.query_testcase_tag() tag_base_map = {} for tag_obj in tag_objs: if tag_obj.tag_category not in tag_base_map: tag_base_map[tag_obj.tag_category] = [{ "tagId": tag_obj.id, "tagName": tag_obj.tag_name }] else: tag_base_map[tag_obj.tag_category].append({ "tagId": tag_obj.id, "tagName": tag_obj.tag_name }) case_obj = self.atim.paging_query_testcase_by_intf_id( intf_id, page_no, page_size, testcase_name=testcase_name) desc_list = [] for i in case_obj.items: case_status_desc = get_desc_by_case_status(i.case_status) last_run_desc = get_desc_by_last_run(i.last_run) tag_relations = self.attrm.get_relations(api_testcase_id=i.id) tag_map = {} for base_category in tag_base_map: tag_map[base_category] = [] for relation in tag_relations: for category, tag_list in tag_base_map.items(): for tag_dic in tag_list: if tag_dic['tagId'] == relation.tag_id: tag_map[category].append(tag_dic) # tag_objs = self.attrm.query_tag_info_by_testcase(i.id) # # tag_id_list = [t_obj[0] for t_obj in tag_objs] if tag_objs else [] # tag_name_list = [t_obj[1] for t_obj in tag_objs] if tag_objs else [] testcases_dict = { "id": i.id, "testcase_name": "{0}__{1}".format(i.testcase_name, i.expect_result), "testcase_desc": i.simple_desc, "expectResult": i.expect_result, "status": case_status_desc, "creator": self.username2nickname_fast(i.creator), "last_modifier": self.username2nickname_fast(i.last_modifier), "last_run": last_run_desc, # "tags_id": tag_id_list, # "tags_name": tag_name_list, "tags": tag_map, "createTime": format(i.create_time) if i.create_time else '', "updateTime": format(i.update_time) if i.update_time else '', "lastRunTime": format(i.last_run_time) if i.last_run_time else '', } desc_list.append(testcases_dict) return make_response({ "code": "000", "desc": desc_list, "totalNum": case_obj.total }) @developer_check def change_status(self): try: testcase_id = self.data.pop("id") except KeyError: return make_response({"code": "100", "desc": "入参校验错误"}) obj = self.atim.get_testcase(id=testcase_id) if obj.case_status == 0: case_status = 1 else: case_status = 0 self.atim.update_testcase(id_=testcase_id, case_status=case_status) return make_response({"code": "000", "desc": "操作成功"}) @developer_check def query_callchain_old(self): """ 查询当前用例的调用链 :return: """ try: testcase_id = self.data.pop("testcaseId") except KeyError: return make_response({"code": "100", "desc": "入参校验错误"}) if not self.atim.get_testcase(id=testcase_id): return make_response({ "code": "200", "desc": "用例id\"{}\"不存在, 请刷新后重试".format(testcase_id) }) res = self.traverse_setup_cases(testcase_id) res[-1]["chain_no"] += " 当前用例" return res def traverse_setup_cases(self, testcase_id): """ 遍历所有前置testcase_id :param testcase_id: :return: """ row = self.atim.query_testcase_belong(testcase_id) if row[0]: setup_cases = eval(row[0])[1]['setup_cases'] else: setup_cases = [] for setup_case_id in setup_cases: if str(testcase_id) != str(setup_case_id): self.traverse_setup_cases(setup_case_id) extract_v_names = '' if row[4]: testset = json.loads(row[4]) for extract_dic in testset['teststeps'][0]['extract']: for v_name in extract_dic: extract_v_names += ', $' + v_name self.chain_no += 1 self.chain_list.append({ "chain_no": str(self.chain_no), "testcase_id": testcase_id, "testcase_name": row[1], "system_name": row[2], "intf_name": row[3], "extract_v_names": extract_v_names.strip(', ') }) return self.chain_list @developer_check def query_callchain(self): """ 查询当前用例的调用链 :return: """ try: testcase_id = self.data.pop("testcaseId") except KeyError: return make_response({"code": "100", "desc": "入参校验错误"}) tc_obj = self.atim.get_testcase(id=testcase_id) if not tc_obj: return make_response({ "code": "200", "desc": "用例id\"{}\"不存在, 请刷新后重试".format(testcase_id) }) res_list = get_testcase_chain(testcase_id, case_type=1, with_intf_system_name=True, with_extract=True) # res_list.reverse() return make_response({"code": "000", "data": res_list}) @developer_with_limit_check def set_tag(self): try: testcase_id = self.data.pop("testcaseId") tag_id_list = self.data.pop("tagIdList") except KeyError: return make_response({"code": "100", "desc": "入参校验错误"}) for tag_id in tag_id_list: if not self.ttm.get_testcase_tag(tag_id): return make_response({ "code": "200", "desc": "标签id\"{}\"不存在, 请刷新后重试".format(tag_id) }) set_testcase_tag(testcase_id, tag_id_list) # objs = self.attrm.get_relations(api_testcase_id=testcase_id) # to_delete_id_list = [str(obj.id) for obj in objs] # # for tag_id in tag_id_list: # obj = self.attrm.get_relation(api_testcase_id=testcase_id, tag_id=tag_id) # if obj and str(obj.id) in to_delete_id_list: # to_delete_id_list.remove(str(obj.id)) # else: # self.attrm.insert_relation(api_testcase_id=testcase_id, tag_id=tag_id) # # for id_ in to_delete_id_list: # self.attrm.delete_relation(id_) return make_response({"code": "000", "desc": "设置标签成功"}) @developer_check def copy_testcase(self): try: testcase_id = self.data.pop('id') count = int(self.data.pop('copyNum')) except KeyError: return make_response({"code": "100", "desc": "入参校验失败"}) obj = self.atim.get_testcase(id=testcase_id) intf_id = obj.api_intf_id pre_obj = self.atim.get_last_obj_by_intf(intf_id) index = pre_obj.index + 1 if pre_obj else 0 table_last_obj = self.atim.get_last_obj() insert_id = table_last_obj.id + 1 if table_last_obj else 1 testcase_insert_list = [] testcase_id_list = [] for i in range(count): case_name = obj.testcase_name + '_copy_{0}_{1}'.format( testcase_id, i + 1) testcase_insert_list.append({ 'id': insert_id + i, 'testcase_name': case_name, 'type': obj.type, 'include': obj.include, 'simple_desc': obj.simple_desc, 'case_status': obj.case_status, 'api_intf_id': obj.api_intf_id, 'creator': self.username, 'expect_result': obj.expect_result, 'index': index + i, 'setup_case_list': obj.setup_case_list, }) testcase_id_list.append(insert_id + i) self.atim.batch_insert_testcase(testcase_insert_list) request_obj = self.atrm.get_request(api_testcase_id=testcase_id) request_insert_list = [] for i in range(count): request_insert_list.append({ 'api_testcase_id': testcase_id_list[i], 'request': request_obj.request }) self.atrm.batch_insert_request(request_insert_list) # 复制tag tag_relation_objs = ApiTestcaseTagRelationManager.get_relations( api_testcase_id=testcase_id) tag_id_list = [str(obj.tag_id) for obj in tag_relation_objs] tag_relation_insert_list = [] for i in range(count): for tag_id in tag_id_list: tag_relation_insert_list.append({ 'api_testcase_id': testcase_id_list[i], 'tag_id': tag_id }) self.attrm.batch_insert_relation(tag_relation_insert_list) return make_response({ "code": "000", "desc": "用例{0}复制成功, 数量{1}".format(testcase_id, count) }) @developer_check def copy_testcase_data(self): """ 复制用例数据结构 :return: """ try: to_testcase_id_list = self.data.pop("copyIdList") from_testcase_id = self.data.pop("copiedId") except KeyError: return make_response({"code": "100", "desc": "入参校验错误"}) from_obj = self.atim.get_testcase(id=from_testcase_id) from_request_obj = self.atrm.get_request( api_testcase_id=from_testcase_id) # 检查是否允许复制 for testcase_id in to_testcase_id_list: to_obj = self.atim.get_testcase(id=testcase_id) if to_obj.api_intf_id != from_obj.api_intf_id: return make_response({ "code": "201", "desc": "用例{}与被复制用例不属于同一接口,无法复制".format(testcase_id) }) tag_relation_objs = ApiTestcaseTagRelationManager.get_relations( api_testcase_id=from_testcase_id) from_tag_id_list = [str(obj.tag_id) for obj in tag_relation_objs] for testcase_id in to_testcase_id_list: self.atim.update_testcase(testcase_id, include=from_obj.include, last_modifier=self.username, setup_case_list=from_obj.setup_case_list) self.atrm.update_request_by_testcase_id( testcase_id, request=from_request_obj.request) # 复制标签 tag_relation_insert_list = [] for tag_id in from_tag_id_list: tag_relation_insert_list.append({ 'testcase_id': testcase_id, 'tag_id': tag_id }) self.attrm.batch_insert_relation(tag_relation_insert_list) return make_response({ "code": "000", "desc": "复制{}数据成功".format(from_testcase_id) }) @developer_check def change_parent(self): try: id_ = self.data.pop('testcaseId') parent_id = self.data.pop('newParentId') except KeyError: return make_response({"code": "100", "desc": "入参校验失败"}) intf_obj = self.aiim.get_intf(id=parent_id) if not intf_obj: return make_response({"code": "200", "desc": "不存在的接口id, 请刷新后重试"}) # 更新原用例集其他用例的index self.atim.index_update_while_remove_testcase(id_=id_) # 获取新用例集的index pre_obj = self.atim.get_last_obj_by_intf(parent_id) index = pre_obj.index + 1 if pre_obj else 0 self.atim.update_testcase(id_=id_, api_intf_id=parent_id, index=index) return make_response({"code": "000", "desc": "ok"}) @developer_check def testcase_detail_with_setup(self): """全链路引入接口用例时使用""" try: testcase_id = self.data.pop("testcaseId") except KeyError: return make_response({"code": "100", "desc": "入参校验错误"}) detail_list = [] chain_objs = get_testcase_chain_objs(testcase_id, case_type=1) for obj_info in chain_objs: if obj_info["case_type"] == 1: tc_obj = obj_info["obj"] detail_dic = get_api_testcase_detail(tc_obj=tc_obj, without_setup_cases=True) detail_dic.pop("include") detail_dic.pop("base") step = detail_dic.pop("steps")[0] intf_obj = self.aiim.get_intf(id=tc_obj.api_intf_id) step.update({ "base": { "intfId": tc_obj.api_intf_id, "intfName": intf_obj.intf_name, "intfNameInChinese": intf_obj.intf_desc, "requestType": intf_obj.intf_type, "subName": tc_obj.testcase_name, "subDesc": tc_obj.simple_desc if tc_obj.simple_desc else '', "subExpectResult": tc_obj.expect_result if tc_obj.expect_result else '' } }) detail_dic.update(step) detail_list.append(detail_dic) elif obj_info["case_type"] == 2: tm_obj = obj_info["obj"] detail_dic = get_api_testcase_main_detail(tm_obj=tm_obj) detail_dic.pop("base") steps_list = detail_dic.pop("steps") for step in steps_list: step["base"].pop("subId", None) detail_list.append(step) return make_response({"code": "000", "dataList": detail_list}) @login_check def query_list_by_setup_case(self): try: testcase_id = self.data.pop("testcaseId", 0) testcase_main_id = self.data.pop("testcaseMainId", 0) if testcase_id: testcase_id = int(testcase_id) elif testcase_main_id: testcase_main_id = int(testcase_main_id) else: raise KeyError except KeyError: return make_response({"code": "100", "desc": "入参校验错误"}) if testcase_id: setupped_case_id_list = get_setupped_case_id_list(testcase_id, 1) else: setupped_case_id_list = get_setupped_case_id_list( testcase_main_id, 2) # 获取{用例id:tag_map} cache = CacheData() tag_base_map = cache.get_tag_base_map() tag_relations = self.attrm.get_relations_in_case_ids( setupped_case_id_list) case_id_tag_map_tmp_dic = {} for case_id in setupped_case_id_list: tag_map = {base_category: [] for base_category in tag_base_map} for relation in tag_relations: if relation.api_testcase_id == case_id: for category, tag_list in tag_base_map.items(): for tag_dic in tag_list: if tag_dic['tagId'] == relation.tag_id: tag_map[category].append(tag_dic) case_id_tag_map_tmp_dic[case_id] = tag_map data_list = [] res = ApiTestcaseInfoManager.get_intf_and_case_info_in_case_ids( setupped_case_id_list) for row in res: data_list.append({ 'intfId': row[0], 'intfName': row[1], 'intfNameInChinese': row[2], 'intfType': row[3], 'id': row[4], 'testcaseName': row[5], 'testcaseCreator': self.username2nickname_fast(row[6]), 'testcaseLasModifier': self.username2nickname_fast(row[7]), 'status': get_desc_by_case_status(row[8]), 'testcaseLastRun': get_desc_by_last_run(row[9]), 'testcaseCreateTime': format(row[10]) if row[10] else '', 'testcaseUpdateTime': format(row[11]) if row[11] else '', 'testcaseLastRunTime': format(row[12]) if row[12] else '', 'tags': case_id_tag_map_tmp_dic[row[4]] }) return make_response({'code': '000', 'dataList': data_list})
def get_all_pv_id_list(self, target_pv_id_list, testcase_id_list=None, testcase_main_id_list=None): if testcase_id_list: for testcase_id in testcase_id_list: obj = self.atim.get_testcase(id=testcase_id) include_list = json_loads(obj.include) public_variables_list = [] for include in include_list: if 'public_variables' in include: public_variables_list = include['public_variables'] # public_variables_list = include_list[0]['public_variables'] # setup_cases_list = include_list[1]['setup_cases'] for public_variable_id in public_variables_list: if public_variable_id not in target_pv_id_list: target_pv_id_list.append(public_variable_id) if obj.setup_case_list: setup_case_list = json_loads(obj.setup_case_list) for setup_case_str in setup_case_list: case_type, case_id, case_flow_id = parse_setup_case_str( setup_case_str) if case_type == 1: testcase_id_list = [case_id] target_pv_id_list = self.get_all_pv_id_list( target_pv_id_list, testcase_id_list=testcase_id_list) elif case_type == 2: testcase_main_id_list = [case_id] target_pv_id_list = self.get_all_pv_id_list( target_pv_id_list, testcase_main_id_list=testcase_main_id_list) elif testcase_main_id_list: exist_main_teardown_var_name = set() # 已加载的全链路独立后置中的公共变量名称集合 for testcase_id in testcase_main_id_list: tm_obj = self.atmm.get_testcase_main(id=testcase_id) sub_list = json_loads(tm_obj.sub_list) for sub_id in sub_list: ts_obj = self.atsm.get_testcase_sub(id=sub_id) include_list = json_loads(ts_obj.include) public_variables_list = include_list[0]['public_variables'] for public_variable_id in public_variables_list: if public_variable_id not in target_pv_id_list: target_pv_id_list.append(public_variable_id) # 处理全链路用例独立后置步骤中的公共变量 if tm_obj.main_teardown_hooks: variable_regexp = r"\$([\w_]+)" main_teardown_variables = re.findall( variable_regexp, str(tm_obj.main_teardown_hooks)) for target in main_teardown_variables: if target in exist_main_teardown_var_name: continue intf_id = ts_obj.api_intf_id intf_obj = ApiIntfInfoManager.get_intf(id=intf_id) system_id = intf_obj.api_system_id s_var_obj = ApiPublicVariableInfoManager.get_variable( variable_name=target, api_system_id=system_id) if s_var_obj: target_pv_id_list.append(s_var_obj.id) else: company_id = ApiSystemInfoManager.get_system( id=system_id).api_company_id c_var_obj = ApiPublicVariableInfoManager.get_variable( variable_name=target, api_company_id=company_id) if c_var_obj: target_pv_id_list.append(c_var_obj.id) exist_main_teardown_var_name.add(target) return target_pv_id_list
class ApiProject(Resource): def __init__(self): self.data = get_request_json() self.username = redis.get_username(request.headers.get('X-Token')) self.acim = ApiCompanyInfoManager() self.asim = ApiSystemInfoManager() self.aiim = ApiIntfInfoManager() self.apim = ApiProjectInfoManager() self.apsrm = ApiProjectSystemRelationManager() self.apirm = ApiProjectIntfRelationManager() @timer def post(self, action): if action == 'add': return self.add_project() elif action == 'edit': return self.edit_project() elif action == 'delete': return self.delete_project() elif action == 'list': return self.project_list_by_company_id() elif action == 'includeSystem': return self.include_system() elif action == 'includeIntf': return self.include_intf() elif action == 'excludeSystem': return self.exclude_system() elif action == 'excludeIntf': return self.exclude_intf() elif action == 'getIncludeIntfList': return self.get_include_intf_list() elif action == 'subtree': return self.subtree() else: return make_response({ "code": "100", "desc": "url错误,不存在的接口动作<{action}>".format(action=action) }) @developer_check def add_project(self): try: company_id = self.data.pop('companyId') project_name = self.data.pop('projectName') simple_desc = self.data.pop('simpleDesc', None) except KeyError: return make_response({"code": "100", "desc": "入参校验失败"}) project_name = str(project_name).strip() if self.apim.get_project(project_name=project_name, api_company_id=company_id): return make_response({ "code": "201", "desc": "公司下存在相同项目名称\"{}\", 无法新增".format(project_name) }) self.apim.insert_project(project_name=project_name, simple_desc=simple_desc, api_company_id=company_id, creator=self.username) return make_response({ "code": "000", "desc": "项目\"{}\"增加成功".format(project_name) }) @developer_check def edit_project(self): try: project_id = self.data.pop('projectId') project_name = self.data.pop('projectName') simple_desc = self.data.pop('simpleDesc', None) except KeyError: return make_response({"code": "100", "desc": "入参校验失败"}) project_obj = self.apim.get_project(id=project_id) if not project_obj: return make_response({ "code": "202", "desc": "项目id\"{}\"不存在, 请刷新后重试".format(project_id) }) exist_project_obj = self.apim.get_project( project_name=project_name, api_company_id=project_obj.api_company_id) if exist_project_obj and exist_project_obj.id != int(project_id): return make_response({ "code": "201", "desc": "公司下存在相同工项目\"{}\", 无法修改".format(project_name) }) self.apim.update_project(project_id, project_name=project_name, simple_desc=simple_desc, last_modifier=self.username) return make_response({ "code": "000", "desc": "公司\"{}\"修改成功".format(project_name) }) @developer_check def delete_project(self): try: project_id = self.data.pop('projectId') except KeyError: return make_response({"code": "100", "desc": "入参校验失败"}) if not self.apim.get_project(id=project_id): return make_response({ "code": "202", "desc": "项目id\"{}\"不存在, 请刷新后重试".format(project_id) }) relation_objs = self.apirm.get_relations(api_project_id=project_id) if relation_objs: return make_response({ "code": "300", "desc": "项目下已引入{}个接口,无法直接删除".format(len(relation_objs)) }) self.apim.delete_project(project_id) return make_response({"code": "000", "desc": "项目删除成功"}) @login_check def project_list_by_company_id(self): try: company_id = int(self.data.pop('companyId', 0)) except KeyError: return make_response({"code": "100", "desc": "入参校验失败"}) if company_id: p_objs = self.apim.get_projects_reverse(api_company_id=company_id) else: p_objs = self.apim.get_projects() # 根据项目分组查询项目中的用例总数 count_res = self.apim.count_api_project_subtree_group_by_project_id( company_id) res_list = [] for p_obj in p_objs: testcase_num = [row[1] for row in count_res if row[0] == p_obj.id][0] if testcase_num: has_children = True else: r_obj = ApiProjectSystemRelationManager.get_relation( api_project_id=p_obj.id) has_children = True if r_obj else False res_list.append({ 'projectId': p_obj.id, 'projectName': p_obj.project_name, 'simpleDesc': p_obj.simple_desc, 'creator': p_obj.creator, 'last_modifier': p_obj.last_modifier, 'hasChildren': has_children, 'testcaseNum': testcase_num, }) return make_response({"code": "000", "projectList": res_list}) @developer_check def include_system(self): try: project_id = self.data.pop('projectId') system_id_list = self.data.pop('systemIdList') except KeyError: return make_response({"code": "100", "desc": "入参校验失败"}) if not system_id_list: return make_response({"code": "200", "desc": "未选择工程,无法引入"}) if len(system_id_list) != len(set(system_id_list)): return make_response({ "code": "101", "desc": "入参校验失败, systemIdList包含重复元素" }) exist_relation_objs = self.apsrm.get_relations( api_project_id=project_id) for exist_relation_obj in exist_relation_objs: if exist_relation_obj.api_system_id in system_id_list: system_id_list.remove(exist_relation_obj.api_system_id) insert_list = [] for system_id in system_id_list: insert_list.append({ 'api_project_id': project_id, 'api_system_id': system_id }) self.apsrm.batch_insert_relation(insert_list) return make_response({ "code": "000", "desc": "{}个工程引入成功".format(len(system_id_list)) }) @developer_check def include_intf(self): try: project_id = self.data.pop('projectId') intf_id_list = self.data.pop('intfIdList') except KeyError: return make_response({"code": "100", "desc": "入参校验失败"}) if not intf_id_list: return make_response({"code": "200", "desc": "未选择接口,无法引入"}) if len(intf_id_list) != len(set(intf_id_list)): return make_response({ "code": "101", "desc": "入参校验失败, intf_id_list包含重复元素" }) exist_relation_objs = self.apirm.get_relations( api_project_id=project_id) for exist_relation_obj in exist_relation_objs: if exist_relation_obj.api_intf_id in intf_id_list: intf_id_list.remove(exist_relation_obj.api_intf_id) insert_list = [] for intf_id in intf_id_list: insert_list.append({ 'api_project_id': project_id, 'api_intf_id': intf_id }) self.apirm.batch_insert_relation(insert_list) return make_response({ "code": "000", "desc": "{}个接口引入成功".format(len(intf_id_list)) }) @developer_check def exclude_system(self): try: project_id = self.data.pop('projectId') system_id = self.data.pop('systemId') except KeyError: return make_response({"code": "100", "desc": "入参校验失败"}) obj = self.apsrm.get_relation(api_project_id=project_id, api_system_id=system_id) if not obj: return make_response({"code": "200", "desc": "此工程未被引入,请刷新后重试"}) p_i_relation_objs = self.apirm.get_relations(api_project_id=project_id) intf_id_list = [ p_i_relation_obj.api_intf_id for p_i_relation_obj in p_i_relation_objs ] intf_objs = self.aiim.get_intfs_in_id_list(intf_id_list) for intf_obj in intf_objs: if intf_obj.api_system_id == int(system_id): return make_response({ "code": "300", "desc": "此工程下已引入接口,无法直接去除" }) self.apsrm.delete_relation(id_=obj.id) return make_response({"code": "000", "desc": "工程去除成功"}) @developer_check def exclude_intf(self): try: project_id = self.data.pop('projectId') intf_id = self.data.pop('intfId') except KeyError: return make_response({"code": "100", "desc": "入参校验失败"}) obj = self.apirm.get_relation(api_project_id=project_id, api_intf_id=intf_id) if not obj: return make_response({"code": "200", "desc": "此接口未被引入,请刷新后重试"}) self.apirm.delete_relation(id_=obj.id) return make_response({"code": "000", "desc": "接口去除成功"}) @developer_check def get_include_intf_list(self): """ Input: {"projectId":"7"} Return: { "code": "000", "includeIntfList": [ 441, 457, 653, 658, 679, 737, 680, 765 ] } """ try: project_id = self.data.pop('projectId') except KeyError: return make_response({"code": "100", "desc": "入参校验失败"}) objs = self.apirm.get_relations(api_project_id=project_id) intf_id_list = [obj.api_intf_id for obj in objs] return make_response({"code": "000", "includeIntfList": intf_id_list}) def subtree(self): try: project_id = int(self.data.pop('projectId')) except (KeyError, ValueError): return make_response({"code": "100", "desc": "入参校验失败"}) subtree = [] index_id = 0 result_list = self.apim.query_api_project_subtree(project_id) patch_result_list = self.apim.query_api_project_subtree_patch( project_id) result_dic = db_result_to_map(result_list, patch_result_list) for p_k, p_dic in result_dic.items(): p_name = p_dic.pop('name') index_id += 1 p_tree = { 'id': index_id, 'label': p_name, 'projectId': p_k, 'children': [] } for s_k, s_dic in p_dic.items(): s_name = s_dic.pop('name') index_id += 1 s_tree = { 'id': index_id, 'label': s_name, 'systemId': s_k, 'children': [] } for i_k, i_dic in s_dic.items(): i_name = i_dic.pop('name') index_id += 1 i_tree = { 'id': index_id, 'label': i_name, 'intfId': i_k, 'children': [] } for t_k, t_dic in i_dic.items(): index_id += 1 t_tree = { 'id': index_id, 'label': '{0}_{1}'.format(t_k, t_dic['name']), 'testcaseId': t_k, } i_tree['children'].append(t_tree) s_tree['children'].append(i_tree) p_tree['children'].append(s_tree) subtree.append(p_tree) return make_response({"code": "000", "data": subtree[0]['children']})
def __init__(self): self.data = get_request_json() self.gdvm = GitDiffVersionManager() self.aiif = ApiIntfInfoManager() self.atim = ApiTaskInfoManager() self.atcm = ApiTestcaseInfoManager()
class CallBack(Resource): def __init__(self): self.data = get_request_json() self.gdvm = GitDiffVersionManager() self.aiif = ApiIntfInfoManager() self.atim = ApiTaskInfoManager() self.atcm = ApiTestcaseInfoManager() @timer def post(self, action): if action == 'getChangesBySeqNo': return self.get_changes_by_seq_no() else: return make_response({"code": "100", "desc": "url错误,不存在的接口动作<{action}>".format(action=action)}) def get_changes_by_seq_no(self): """ 根据流水号获取变更内容 :return: """ try: seq_no = self.data.pop('seq_no') application = self.data.pop('application') except KeyError: return make_response({"code": "100", "mes": CODE_DESC_MAP["100"]}) git_diffs = self.gdvm.get_git_diff_versions(seq_no=seq_no) if not git_diffs: return make_response({"code": "100", "desc": "seq_no不存在"}) elif len(git_diffs) > 1: return make_response({"code": "100", "desc": "seq_no不唯一"}) else: changes = application['changes'] api_task_id = git_diffs[0].api_task_id self.gdvm.update_git_diff_version_by_seq_no(seq_no_=seq_no, detail=json_dumps(changes)) self.update_task_info(api_task_id, changes, seq_no) return make_response({"code": "0000", "msg": "成功"}) def update_task_info(self, api_task_id, changes, seq_no): """ 解析回调接口返回的变更内容 :param api_task_id: :param changes: :param seq_no: :return: """ affect_http = set() affect_dubbo = set() affect_mq = set() affect_elasticJob = set() for affects in [change['affects'] for change in changes]: for methods in [affect['methods'] for affect in affects]: for method in methods: if method.get('http'): method_http = method.get('http').get('url') affect_http.add(method_http) if method.get('dubbo'): role = method.get('dubbo').get('role') method_dubbo = method.get('dubbo').get('service').get('interface') + '.' + method.get('method') \ if role == 'service' else method.get('dubbo').get('reference').get( 'interface') + '.' + method.get('method') affect_dubbo.add(method_dubbo) if method.get('mq'): role = method.get('mq').get('role') method_mq = method.get('mq').get('producer').get('topic') \ if role == 'producer' else method.get('mq').get('consumer').get( 'topic') + '.' + method.get('mq').get('consumer').get( 'tag') affect_mq.add(method_mq) if method.get('elasticJob'): method_elasticJob = method.get('elasticJob').get('class') + '.' + method.get('method') affect_elasticJob.add(method_elasticJob) affects = { "http": list(affect_http), "dubbo": list(affect_dubbo), "mq": list(affect_mq), "elasticJob": list(affect_elasticJob)} # 查询atp平台是否存在对应接口,如有则将接口id填入effect_intf_id_list,如无则将接口数据填入uncovered_info task_info = self.atim.get_task(id=api_task_id) effect_intf_id_list = set(json_loads(task_info.effect_intf_id_list)) if task_info.effect_intf_id_list else set() uncovered_info = json_loads(task_info.uncovered_info) if task_info.uncovered_info else {} uncovered_info_http = set(uncovered_info.get('http')) if uncovered_info.get('http') else set() uncovered_info_dubbo = set(uncovered_info.get('dubbo')) if uncovered_info.get('dubbo') else set() uncovered_info_mq = set(uncovered_info.get('mq')) if uncovered_info.get('mq') else set() uncovered_info_elasticJob = set(uncovered_info.get('elasticJob')) if uncovered_info.get('elasticJob') else set() for intf_name in affects['http']: if intf_name: intf_info = self.aiif.get_intf(intf_name=intf_name) if intf_info: testcase_info = self.atcm.get_testcase(api_intf_id=intf_info.id) if testcase_info: affects['http'] = affects['http'].remove(intf_name) effect_intf_id_list.add(intf_info.id) else: uncovered_info_http.add(intf_name) else: uncovered_info_http.add(intf_name) for intf_name in affects['dubbo']: if intf_name: intf_info = self.aiif.get_intf(intf_name=intf_name) if intf_info: testcase_info = self.atcm.get_testcase(api_intf_id=intf_info.id) if testcase_info: affects['dubbo'] = affects['dubbo'].remove(intf_name) effect_intf_id_list.add(intf_info.id) else: uncovered_info_dubbo.add(intf_name) else: uncovered_info_dubbo.add(intf_name) for intf_name in affects['mq']: if intf_name: intf_info = self.aiif.get_intf(intf_name=intf_name) if intf_info: testcase_info = self.atcm.get_testcase(api_intf_id=intf_info.id) if testcase_info: affects['mq'] = affects['mq'].remove(intf_name) effect_intf_id_list.add(intf_info.id) else: uncovered_info_mq.add(intf_name) else: uncovered_info_mq.add(intf_name) for intf_name in affects['elasticJob']: if intf_name: intf_info = self.aiif.get_intf(intf_name=intf_name) if intf_info: testcase_info = self.atcm.get_testcase(api_intf_id=intf_info.id) if testcase_info: affects['elasticJob'] = affects['elasticJob'].remove(intf_name) effect_intf_id_list.add(intf_info.id) else: uncovered_info_elasticJob.add(intf_name) else: uncovered_info_elasticJob.add(intf_name) effect_intf_id_list = list(effect_intf_id_list) uncovered_info['http'] = list(uncovered_info_http) uncovered_info['dubbo'] = list(uncovered_info_dubbo) uncovered_info['mq'] = list(uncovered_info_mq) uncovered_info['elasticJob'] = list(uncovered_info_elasticJob) # 判断当前是否是同一个api_task下的最后一个回调,如果是则更新api_task_info表里面对应记录的task_status为1(启动) git_diffs = self.gdvm.get_git_diff_versions_special(seq_no, api_task_id) if not git_diffs: self.atim.update_task(api_task_id, effect_intf_id_list=json_dumps(effect_intf_id_list), uncovered_info=json_dumps(uncovered_info), task_status=1) else: flag = 0 for row in git_diffs: if not row.detail: flag = 1 break if flag == 1: self.atim.update_task(api_task_id, effect_intf_id_list=json_dumps(effect_intf_id_list), uncovered_info=json_dumps(uncovered_info)) if flag == 0: self.atim.update_task(api_task_id, effect_intf_id_list=json_dumps(effect_intf_id_list), uncovered_info=json_dumps(uncovered_info), task_status=1)
def init_table_api_intf_default_request(): """初始化api_intf_default_request表""" intf_objs = aiim.get_intfs() # tc_objs = atim.get_testcases() process_len = len(intf_objs) process_id = 0 for intf_obj in intf_objs: print('intf_id: {}'.format(intf_obj.id)) t1 = time.time() process_id += 1 print('{:.1f}%'.format(process_id*100.0/process_len)) if aidrm.get_request(api_intf_id=intf_obj.id): continue tc_objs = atim.get_testcases(api_intf_id=intf_obj.id) final_body = None for tc_obj in tc_objs: tc_request_obj = atrm.get_request(api_testcase_id=tc_obj.id) if not tc_request_obj or not tc_request_obj.request: continue request_dic = json_loads(tc_request_obj.request) try: if tc_obj.type == 1: body = request_dic['teststeps'][0]['request']['json'] if not final_body: final_body = body else: final_body = merge_request_body(final_body, body) elif tc_obj.type == 2: body = request_dic['teststeps'][0]['request']['json']['args'] if not final_body: final_body = body else: final_body = merge_request_body(final_body, body, is_list=True) elif tc_obj.type == 3: body_str = request_dic['teststeps'][0]['request']['json']['msg'] body = json_loads(body_str) if not final_body: final_body = body else: final_body = merge_request_body(final_body, body) else: continue except KeyError: print('Error!!') continue t3 = time.time() d_time = t3 - t1 print("==== Finish t3, run {:.3}s ====\n".format(d_time)) if final_body is not None: body = remove_var_mark(final_body) p = ParseBodyToDetail(body) p.parse_main() detail_str = json_dumps(p.detail) body_str = json_dumps(body) aidrm.insert_request(api_intf_id=intf_obj.id, request=body_str, request_detail=detail_str)