def use_case_detail(): """ 功能描述: 获取某个use_case的详细信息,包括其包含的interface列表 1. 根据use_case_id获取use_case基本信息 2. 根据use_case_id获取use_case与interface的关联信息 3. 根据关联信息的id查出所有interface的名称信息以及定义的参数信息 4. 信息整理并返回 :return: """ use_case_info = Case_API.get_use_case(**request.get_json(force=True))[0] use_case_info.update({'interface_list': []}) relation_interface_list = Case_API.get_relation( use_case_id=use_case_info.get('id')) for relation_interface in relation_interface_list: relation_interface.pop('use_case_id') relation_interface.pop('create_time') relation_interface.pop('update_time') interface_id = relation_interface.get('interface_id') interface_list = InterfaceAPI.get_interface(id=interface_id) relation_interface.update( {'interface_name': interface_list[0].get('interface_name')}) para_list = Case_API.get_case_parameter_relation( relation_id=relation_interface['id']) relation_interface.update({'param_list': para_list}) use_case_info['interface_list'].append(relation_interface) return jsonify({'success': True, 'res': use_case_info})
def modify_interface(): """ 更新interface信息 1. 获取原interface参数信息 2. 将更新的interface内容写入数据库 3. 如果新旧参数无区别, 结束并返回 4. 如果新旧参数有区别, 更新所有use_case传给此interface的参数记录 """ interface_id = request.get_json().get('id') interface_old_info = InterfaceAPI.get_interface(id=interface_id)[0] InterfaceAPI.modify_interface(**request.get_json()) interface_new_info = InterfaceAPI.get_interface(id=interface_id)[0] relation_list = UseCaseAPI.get_relation(interface_id=interface_id) old_analysis_str = ''.join([ interface_old_info.get('interface_header'), interface_old_info.get('interface_json_payload'), interface_old_info.get('interface_url') ]) new_analysis_str = ''.join([ interface_new_info.get('interface_header'), interface_new_info.get('interface_json_payload'), interface_new_info.get('interface_url') ]) old_param_list = search_parameter(old_analysis_str) new_param_list = search_parameter(new_analysis_str) update_param_list = list(set(old_param_list) ^ set(new_param_list)) if len(update_param_list) == 0: return jsonify({'success': True}) else: for param in update_param_list: if '==' in param: parameter_value = param.split('==')[1] parameter_name = param.split('==')[0] else: parameter_value = '' parameter_name = param if param in old_param_list: for p_relation in relation_list: UseCaseAPI.del_case_parameter_relation( parameter_name=parameter_name, relation_id=p_relation['id']) else: # 新增参数添加到各个用例中去 for relation in relation_list: kwargs = { 'relation_id': relation['id'], 'parameter_name': parameter_name, 'parameter_value': parameter_value } UseCaseAPI.add_case_parameter_relation(**kwargs) return jsonify({'success': True})
def delete_interface(): """ 删除某个interface 1. 将interface数据从数据库中标记为已删除 2. 将所有use_case与此interface的关联关系标记为已删除 3. 将所有use_case传给此interface的参数记录标记为已删除 """ interface_id = request.get_json().get('id') relation_list = UseCaseAPI.get_relation(interface_id=interface_id) for interface_relation in relation_list: parameter_info = UseCaseAPI.get_case_parameter_relation(id=interface_relation['id']) for s_prama_relation in parameter_info: UseCaseAPI.del_case_parameter_relation(id=s_prama_relation['id']) UseCaseAPI.del_relation(interface_relation['id']) InterfaceAPI.del_interface(**request.get_json()) return jsonify({'success': True})
def delete_interface(): """ 删除某个interface 1. 将interface数据从数据库中标记为已删除 2. 将所有use_case与此interface的关联关系标记为已删除 3. 将所有use_case传给此interface的参数记录标记为已删除 """ user_id = cur_user() interface_id = request.get_json().get('id') relation_list = UseCaseAPI.get_relation(interface_id=interface_id) if relation_list and user_id not in app.config['SUPER_MANAGER']: return jsonify({'success': False, 'error': '存在关联用例, 需解除关联用例(或者管理员)删除'}) for interface_relation in relation_list: parameter_info = UseCaseAPI.get_case_parameter_relation( id=interface_relation['id']) for s_prama_relation in parameter_info: UseCaseAPI.del_case_parameter_relation(id=s_prama_relation['id']) UseCaseAPI.del_relation(interface_relation['id']) InterfaceAPI.del_interface(**request.get_json()) return jsonify({'success': True})
except Exception as e: return { 'success': False, 'error_str': '接口{0}数据库'.format(interface_count), 'res': exec_result_list, 'error': '{0}: {1}'.format(str(e.__class__.__name__), str(e)), 'batch_log_id': batch_log_id, 'use_case_count': use_case_count, 'batch_start_timer': batch_start_timer } # 获取用例信息以及用例下接口信息 try: use_case_info = UseCaseAPI.get_use_case(id=use_case_id)[0] if relation_id: interface_list = UseCaseAPI.get_relation(id=relation_id) else: interface_list = UseCaseAPI.get_relation(use_case_id=use_case_id) except Exception as e: use_case_exception_log_update(use_case_log_id, use_case_start) return { 'success': False, 'error_str': '接口{0}数据库'.format(interface_count), 'res': exec_result_list, 'error': '{0}: {1}'.format(str(e.__class__.__name__), str(e)), 'batch_log_id': batch_log_id, 'use_case_count': use_case_count, 'batch_start_timer': batch_start_timer } try: use_case_info['interface_list'] = []
def run_use_case(use_case_id, batch_log_id=None, environment_id=None, relation_id=None, use_case_count=None, batch_start_timer=None, auto_run=False, alarm_monitor=False): # if async: # engine.dispose() exec_result_list = [] interface_count = 1 # 信息初始化 start_time = datetime.utcnow() use_case_start = timeit.default_timer() run_pass = True use_case_log_info = { 'use_case_id': use_case_id, 'start_time': start_time, 'auto_run': auto_run } if batch_log_id: use_case_log_info['batch_run_log_id'] = batch_log_id try: use_case_log_id = RunLogAPI.add_use_case_run_log(**use_case_log_info) except Exception as e: error = '{0}: {1}'.format(str(e.__class__.__name__), str(e)) return except_result(interface_count, exec_result_list, error, batch_log_id, use_case_count, batch_start_timer) # 获取用例信息以及用例下接口信息 try: use_case_info = UseCaseAPI.get_use_case(id=use_case_id)[0] if relation_id: interface_list = UseCaseAPI.get_relation(id=relation_id) else: interface_list = UseCaseAPI.get_relation(use_case_id=use_case_id) except Exception as e: use_case_exception_log_update(use_case_log_id, use_case_start) error = '{0}: {1}'.format(str(e.__class__.__name__), str(e)) return except_result(interface_count, exec_result_list, error, batch_log_id, use_case_count, batch_start_timer) try: use_case_info['interface_list'] = [] # 对用例中使用预定义参数的做参数替换 for interface_relation in interface_list: eval_string = interface_relation['eval_string'] interface_id = interface_relation['interface_id'] interface_info = InterfaceAPI.get_interface(id=interface_id)[0] interface_info['interface_delay'] = interface_relation[ 'interface_delay'] interface_info['eval_string'] = eval_string interface_info['param_define_list'] = get_param_define_list( interface_relation['id']) use_case_info['interface_list'].append(interface_info) interface_list = use_case_info['interface_list'] except Exception as e: # 用例运行日志记录 use_case_exception_log_update(use_case_log_id, use_case_start) error = '{0}: {1}'.format(str(e.__class__.__name__), str(e)) return except_result(interface_count, exec_result_list, error, batch_log_id, use_case_count, batch_start_timer) function_id = use_case_info['function_id'] email_addrs = EmailAPI.query_email_by_function_id(function_id) addr_dicts = { email['email_address'].split('@')[0]: email['email_address'] for email in email_addrs } # 由于线上环境配置有host,所以监控模式下,也要配置环境信息 if batch_log_id: environment_id = environment_id else: environment_id = environment_id or use_case_info['environment_id'] environment_info = EnvironmentAPI.get_environment_line_info( environment_id=environment_id) url_map_ip = dict() for element in environment_info: url = element['url'].strip() ip_address = element['map_ip'].strip() url_map_ip[url] = ip_address encryption_dict = EncryptionAPI.get_encryption_id_to_name() with requests.Session() as session: for interface in interface_list: # 添加延时运行接口 interface_delay = int(interface.get('interface_delay')) if interface_delay > 0: time.sleep(interface_delay) interface_name = interface.get('interface_name') interface_log_dict = { 'interface_start_time': datetime.utcnow(), 'use_case_run_log_id': use_case_log_id, 'interface_id': interface['id'] } try: # 将接口未替换的参数全部替换 request_method = interface['interface_method'] result_list = get_item_to_rephrase( interface, exec_result_list, data_type=interface['body_type']) url, header, json_payload = result_list except Exception as e: # 数据处理以及日志记录 interface_log_dict['is_pass'] = False interface_log_dict['error_message'] = '参数替换: {0}: {1}'.format( str(e.__class__.__name__), str(e)) interface_log_insert(interface_log_dict) # 用例运行日志记录 use_case_exception_log_update(use_case_log_id, use_case_start) error = '{0}: {1}'.format(str(e.__class__.__name__), str(e)) return except_result(interface_count, exec_result_list, error, batch_log_id, use_case_count, batch_start_timer) try: # 加密 if interface['body_type'] == 0 and json_payload: requested_interface = get_remote_interface_name( json.loads(json_payload), interface, url) else: requested_interface = get_remote_interface_name( '', interface, url) if header: header = json.loads(header) if json_payload: if interface['interface_encryption'] != 0: encryption_method = encryption_dict[ interface['interface_encryption']] method = getattr(Encryption, encryption_method) if interface['interface_encryption'] in [1, 4]: header = method(json_payload, header) elif interface['interface_encryption'] == 5: url, json_payload = method(url, json_payload) else: json_payload = method(json_payload) except Exception as e: # 数据处理以及日志记录 print(e) interface_log_dict['is_pass'] = False interface_log_dict[ 'error_message'] = 'json处理或加密: {0}: {1}'.format( str(e.__class__.__name__), str(e)) interface_log_dict['s_header'] = str(header) interface_log_dict['s_payload'] = str(json_payload) interface_log_dict['interface_start'] = timeit.default_timer() interface_log_insert(interface_log_dict) # 用例运行日志记录 use_case_exception_log_update(use_case_log_id, use_case_start) error = '{0}: {1}'.format(str(e.__class__.__name__), str(e)) return except_result(interface_count, exec_result_list, error, batch_log_id, use_case_count, batch_start_timer) # 请求接口参数准备 request_kwargs = {'timeout': 30} if header: request_kwargs['headers'] = header else: request_kwargs['headers'] = dict() if json_payload: request_kwargs.update({'json': json_payload}) if interface['body_type'] == 0 \ else request_kwargs.update({"data": json_payload}) # 获取域名对应的服务名 server_name = get_server_name(url) # 获取方法ID, 接口名 # 日志内容 interface_log_dict['s_header'] = json.dumps( header, ensure_ascii=False) if header else '' if interface['body_type'] == 0: interface_log_dict['s_payload'] = json.dumps( json_payload, ensure_ascii=False) if json_payload else '' else: interface_log_dict['s_payload'] = json_payload interface_log_dict['interface_start'] = timeit.default_timer() request_exception = False log_report_code = 0 error_string = '' json_response = result = dict() request_method = request_method.upper() request_kwargs['headers']['Connection'] = 'close' try: url_netloc = url.rsplit('/') prefix = '//'.join([url_netloc[0], url_netloc[2]]) host_name = url_netloc[2] if environment_id: source_address = url_map_ip.get(host_name, None) session.mount(prefix, CustomAdapter(source_address=source_address)) r = session.request(request_method, url, **request_kwargs) time.sleep(0.01) r.encoding = 'utf-8' try: json_response = r.json() json_flag = True except Exception as e: json_flag = False r_type = r.headers['Content-Type'] if 'application/json' != r_type: json_response = r.content.decode() else: json_response = {} interface_log_dict['interface_stop'] = timeit.default_timer() result = { 'r_request': request_kwargs, 'status_code': r.status_code, 'header': dict(r.headers), 'json_response': json_response, 'interface_name': interface_name } interface_log_dict['r_code'] = r.status_code interface_log_dict['r_header'] = json.dumps(result['header'], ensure_ascii=False) if json_flag: interface_log_dict['r_payload'] = json.dumps( result['json_response'], ensure_ascii=False) elif interface['interface_encryption'] == 6: interface_log_dict['r_payload'] = json.dumps( json_response, ensure_ascii=False) else: r.encoding = 'utf-8' interface_log_dict['r_payload'] = r.text result['json_response'] = '<iframe srcdoc="{}" style="width:100%;height:60vh" ' \ 'frameborder="0"></iframe>'.format(html.escape(r.text)) except ConnectTimeout as e: request_exception = True error_string = '{0}: {1} ,{2}'.format( '请求服务连接超时', str(e.__class__.__name__), str(e)) log_report_code = '9991' except ConnectionError as e: if os.getpid() in g_DNS.get_dns(): dns_info = g_DNS.get_dns()[os.getpid()] LOGGER.info_log('连接失败,环境映射信息:{}, 当前url:{}'.format( dns_info, url)) request_exception = True error_string = '{0},{1}: {2}'.format('请求服务连接失败', str(e.__class__.__name__), str(e)) log_report_code = '9992' except KeyError as e: request_exception = True error_string = '错误代码行{0}: {1}'.format(sys._getframe().f_lineno, str(e)) log_report_code = '9993' except Exception as e: request_exception = True error_string = '{0}: {1},{2}'.format(sys._getframe().f_lineno, str(e.__class__.__name__), str(e)) log_report_code = '9994' finally: if request_exception: if alarm_monitor and not app.config['DEBUG']: cost_time = timeit.default_timer( ) - interface_log_dict['interface_start'] LOGGER.request_log(server_name, server_name, requested_interface, log_report_code, str(cost_time)) message = get_email_body( use_case_info['use_case_name'], interface_name, error_string, use_case_log_id) executor.submit(execute_fail_email, addr_dicts, message) # 数据处理以及日志记录 interface_log_dict['is_pass'] = False interface_log_dict['error_message'] = '{0}'.format( error_string) interface_log_insert(interface_log_dict) # 用例运行日志记录 use_case_exception_log_update(use_case_log_id, use_case_start) return except_result(interface_count, exec_result_list, error_string, batch_log_id, use_case_count, batch_start_timer) try: # 验证接口返回 eval_success = eval_interface_result(result, interface['eval_string'], exec_result_list) result['success'] = eval_success run_pass = run_pass and eval_success exec_result_list.append(result) # 数据处理以及日志记录 interface_log_dict['is_pass'] = result['success'] executor.submit(interface_log_insert, interface_log_dict) if alarm_monitor and not app.config['DEBUG']: executor.submit(monitor_request, interface_log_dict, json_response, eval_success, server_name, requested_interface) if not result['success']: message = get_email_body( use_case_info['use_case_name'], interface_name, '返回结果验证失败', use_case_log_id) executor.submit(execute_fail_email, addr_dicts, message) if not result['success']: break except Exception as e: result['success'] = False exec_result_list.append(result) # 数据处理以及日志记录 interface_log_dict['is_pass'] = result['success'] exc_type, exc_obj, exc_tb = sys.exc_info() error = '{0}: {1}'.format(str(e.__class__.__name__), str(e)) interface_log_dict['error_message'] = '验证: {0}: {1},异常信息:{2}'. \ format(str(e.__class__.__name__), str(e), str(traceback.extract_tb(exc_tb))) if alarm_monitor and not app.config['DEBUG']: message = get_email_body( use_case_info['use_case_name'], interface_name, interface_log_dict['error_message'], use_case_log_id) executor.submit(execute_fail_email, addr_dicts, message) interface_log_insert(interface_log_dict) # 用例运行日志记录 use_case_exception_log_update(use_case_log_id, use_case_start) return except_result(interface_count, exec_result_list, error, batch_log_id, use_case_count, batch_start_timer) interface_count += 1 # 用例运行日志记录 use_case_stop = timeit.default_timer() end_time = datetime.utcnow() RunLogAPI.modify_use_case_run_log( **{ 'id': use_case_log_id, 'is_pass': run_pass, 'end_time': end_time, 'cost_time': use_case_stop - use_case_start }) response = { 'pass': run_pass, 'res': exec_result_list, 'batch_log_id': batch_log_id, 'use_case_count': use_case_count, 'batch_start_timer': batch_start_timer } return response