예제 #1
0
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})
예제 #2
0
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})
예제 #3
0
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})
예제 #4
0
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})
예제 #5
0
    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'] = []
예제 #6
0
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