def check_json(src_data, dst_data, success):
    """
    校验的json
    :param src_data:  校验内容
    :param dst_data:  接口返回的数据(被校验的内容)
    :param success:  全局测试结果
    :return:
    """
    global result
    if isinstance(src_data, dict):
        # 若为dict格式
        for key in src_data:
            if key not in dst_data:
                success["result"] = False
                raise failureException("JSON格式校验,关键字 %s 不在返回结果 %s" %
                                       (key, dst_data))
            else:
                this_key = key
                # 递归
                if isinstance(src_data[this_key], dict) and isinstance(
                        dst_data[this_key], dict):
                    check_json(src_data[this_key], dst_data[this_key], success)
                elif isinstance(type(src_data[this_key]),
                                type(dst_data[this_key])):
                    success["result"] = False
                    raise failureException(
                        "JSON格式校验,关键字 %s 与 %s 类型不符" %
                        (src_data[this_key], dst_data[this_key]))
                else:
                    pass
    else:
        success["result"] = False
        raise failureException("JSON校验内容非dict格式")
def get_time(time_type, layout, unit="0,0,0,0,0"):
    """
    获取时间
    :param time_type: 现在的时间now, 其他时间else_time
    :param layout: 10timestamp, 13timestamp,  else  时间类型
    :param unit: 时间单位: [seconds, minutes, hours, days, weeks] 秒,分,时,天,周
    :return:
    """
    tim = datetime.datetime.now()
    if time_type != "now":
        lag = unit.split(",")
        try:
            tim = tim + datetime.timedelta(seconds=int(lag[0]),
                                           minutes=int(lag[1]),
                                           hours=int(lag[2]),
                                           days=int(lag[3]),
                                           weeks=int(lag[4]))
        except ValueError:
            raise failureException("获取时间错误,时间单位%s" % unit)
    # 获取10位时间戳
    if layout == "10timestamp":
        tim = tim.strftime('%Y-%m-%d %H:%M:%S')
        tim = int(time.mktime(time.strptime(tim, "%Y-%m-%d %H:%M:%S")))
        return tim
    # 获取13位时间戳
    elif layout == "13timestamp":
        tim = tim.strftime('%Y-%m-%d %H:%M:%S')
        tim = int(time.mktime(time.strptime(tim, "%Y-%m-%d %H:%M:%S")))
        tim = int(round(tim * 1000))
        return tim
    # 按传入格式获取时间
    else:
        tim = tim.strftime(layout)
        return tim
def read_json(test_name, code_json, relevance, _path, result):
    """
    校验内容读取
    :param test_name: 用例名称,用作索引
    :param code_json: 文件路径
    :param relevance: 关联对象
    :param _path: case路径
    :param result: 全局结果
    :return:
    """
    # 用例中参数为json格式
    if isinstance(code_json, dict):
        code_json = manage(code_json, relevance)
    # 用例中参数非json格式
    else:
        try:
            with open(_path + "/" + code_json, "r", encoding="utf-8") as f:
                data = json.load(f)
                for i in data:
                    # 遍历,通过用例名称做索引查找到第一个期望结果后,跳出循环
                    if i["test_name"] == test_name:
                        code_json = i["json"]
                        break
                # 如果code_json为空,表示未找到用例关联的期望结果
                if not code_json:
                    result["result"] = False
                    raise failureException("未找到用例关联的期望结果\n文件路径: %s\n索引: %s" %
                                           (code_json, test_name))
                else:
                    code_json = manage(code_json, relevance)
        # 文件不存在
        except FileNotFoundError:
            result["result"] = False
            raise failureException("用例关联文件不存在\n文件路径: %s" % code_json)
        # 文件存在,但里面存储的数据有误,json.load执行异常
        except JSONDecodeError:
            result["result"] = False
            raise failureException("用例关联的期望文件有误\n文件路径: %s" % code_json)
    # 返回获取的期望结果
    return code_json
def random_string(num_length):
    """
    从a-zA-Z0-9生成指定数量的随机字符
    :param num_length: 字符串长度
    :return:
    """
    try:
        num_length = int(num_length)
    except ValueError:
        raise failureException("从a-zA-Z0-9生成指定数量的随机字符失败!长度参数有误  %s" %
                               num_length)
    num = ''.join(
        random.sample(string.ascii_letters + string.digits, num_length))
    return num
示例#5
0
def read_param(test_name, param, relevance, _path, result):
    """
    判断用例中参数类型
    :param test_name: 用例名称
    :param param:
    :param relevance: 关联对象
    :param _path: case路径
    :param result: 全局结果
    :return:
    """
    # 用例中参数为json格式
    if isinstance(param, dict):
        param = manage(param, relevance)
    # 用例中参数非json格式
    else:
        try:
            with open(_path + "/" + param, "r", encoding="utf-8") as f:
                data = json.load(f)
                for i in data:
                    # 通过test_name索引,提取第一个匹配到的用例参数
                    if i["test_name"] == test_name:
                        param = i["parameter"]
                        break
                # 为空,未匹配到
                if not isinstance(param, dict):
                    result["result"] = False
                    raise failureException("未找到用例关联的参数\n文件路径: %s\n索引: %s" %
                                           (param, test_name))
                else:
                    param = manage(param, relevance)
        except FileNotFoundError:
            result["result"] = False
            raise failureException("用例关联文件不存在\n文件路径: %s" % param)
        except JSONDecodeError:
            result["result"] = False
            raise failureException("用例关联的参数文件有误\n文件路径: %s" % param)
    return param
def random_int(scope):
    """
    获取随机整型数据
    :param scope: 时间范围
    :return:
    """
    try:
        start_num, end_num = scope.split(",")
        start_num = int(start_num)
        end_num = int(end_num)
    except ValueError:
        raise failureException("调用随机整数失败,范围参数有误!\n %s" % str(scope))
    if start_num <= end_num:
        num = random.randint(start_num, end_num)
    else:
        num = random.randint(end_num, start_num)
    return num
示例#7
0
def ini_request(case_dict, relevance, _path, result):
    """
    用例前提条件执行,提取关联键
    :param case_dict: 用例对象
    :param relevance:  关联对象
    :param _path:  case路径
    :param result:  全局结果
    :return:
    """
    if isinstance(case_dict["premise"], list):
        logging.info("执行测试用例前置接口")
        with allure.step("接口关联请求"):
            for i in case_dict["premise"]:
                relevance_list = relevance.copy()
                for j in range(0, 3):
                    # 获取前置接口关联数据失败
                    code, data = send_request(
                        i, case_dict["testinfo"].get("host"),
                        case_dict["testinfo"].get("address"), relevance_list,
                        _path, result)
                    if not data:
                        with allure.step("接口请求失败!等待三秒后重试!"):
                            pass
                        logging.info("接口请求失败!等待三秒后重试!")
                        continue
                    if i["relevance"]:
                        if len(i["relevance"]):
                            relevance = get_relevance(data, i["relevance"],
                                                      relevance)
                            if isinstance(relevance, bool):
                                with allure.step("从结果中提取关联键的值失败!等待3秒后重试!"):
                                    pass
                                logging.info("从结果中提取关联键的值失败!等待3秒后重试!")
                                time.sleep(3)
                                continue
                            else:
                                break
                        else:
                            break
                    else:
                        break
                if isinstance(relevance, bool):
                    logging.info("从结果中提取关联键的值失败!重试三次失败")
                    result["result"] = False
                    raise failureException("获取前置接口关联数据失败")
    return relevance
def random_float(data):
    """
    获取随机整型数据
    :param data:
    :return:
    """
    try:
        start_num, end_num, accuracy = data.split(",")
        start_num = int(start_num)
        end_num = int(end_num)
        accuracy = int(accuracy)
    except ValueError:
        raise failureException("调用随机整数失败,范围参数或精度有误!\n小数范围精度 %s" % data)
    if start_num <= end_num:
        num = random.uniform(start_num, end_num)
    else:
        num = random.uniform(end_num, start_num)
    num = round(num, accuracy)
    return num
def check(test_name, case_data, code, data, relevance, _path, success):
    """
    校验测试结果
    :param test_name:  测试用例
    :param case_data:  测试用例
    :param code:  HTTP状态
    :param data:  返回的接口json数据
    :param relevance:  关联值对象
    :param _path:  case路径
    :param success:  全局测试结果
    :return:
    """
    # 不校验
    if case_data["check_type"] == 'no_check':
        with allure.step("不校验结果"):
            pass

    # 校验json格式
    elif case_data["check_type"] == 'json':
        expected_request = case_data["expected_request"]
        # 判断预期结果格式,如果是字符串,则打开文件路径,提取保存在文件中的期望结果
        if isinstance(case_data["expected_request"], str):
            expected_request = expectedManage.read_json(
                test_name, expected_request, relevance, _path, success)
        with allure.step("JSON格式校验"):
            allure.attach("期望code", str(case_data["expected_code"]))
            allure.attach('期望data', str(expected_request))
            allure.attach("实际code", str(code))
            allure.attach('实际data', str(data))
        if int(code) == case_data["expected_code"]:
            if not data:
                data = "{}"
            # json校验
            CheckJson.check_json(expected_request, data, success)
        else:
            success["result"] = False
            if case_data.get("CustomFail"):
                info = CustomFail.custom_manage(case_data.get("CustomFail"),
                                                relevance)
                raise failureException(
                    str(info) + "\nhttp状态码错误!\n %s != %s" %
                    (code, case_data["expected_code"]))
            else:
                raise failureException("http状态码错误!\n %s != %s" %
                                       (code, case_data["expected_code"]))

    # 只校验HTTP状态
    elif case_data["check_type"] == 'only_check_status':
        with allure.step("校验HTTP状态"):
            allure.attach("期望code", str(case_data["expected_code"]))
            allure.attach("实际code", str(code))
        if int(code) == case_data["expected_code"]:
            pass
        else:
            success["result"] = False
            if case_data.get("CustomFail"):
                info = CustomFail.custom_manage(case_data.get("CustomFail"),
                                                relevance)
                raise failureException(
                    str(info) + "\nhttp状态码错误!\n %s != %s" %
                    (code, case_data["expected_code"]))
            else:
                raise failureException("http状态码错误!\n %s != %s" %
                                       (code, case_data["expected_code"]))

    # 完全校验
    elif case_data["check_type"] == 'entirely_check':
        expected_request = case_data["expected_request"]
        # 判断预期结果格式,如果是字符串,则打开文件路径,提取保存在文件中的期望结果
        if isinstance(case_data["expected_request"], str):
            expected_request = expectedManage.read_json(
                test_name, expected_request, relevance, _path, success)
        with allure.step("完全校验"):
            allure.attach("期望code", str(case_data["expected_code"]))
            allure.attach('期望data', str(expected_request))
            allure.attach("实际code", str(code))
            allure.attach('实际data', str(data))
        if int(code) == case_data["expected_code"]:
            result = operator.eq(expected_request, data)
            if result:
                pass
            else:
                success["result"] = False
                if case_data.get("CustomFail"):
                    info = CustomFail.custom_manage(
                        case_data.get("CustomFail"), relevance)
                    raise failureException(
                        str(info) + "\n完全校验失败! %s ! = %s" %
                        (expected_request, data))
                else:
                    raise failureException("完全校验失败! %s ! = %s" %
                                           (expected_request, data))
        else:
            success["result"] = False
            raise failureException("http状态码错误!\n %s != %s" %
                                   (code, case_data["expected_code"]))

    # 正则校验
    elif case_data["check_type"] == 'Regular_check':
        if int(code) == case_data["expected_code"]:
            try:
                result = ""  # 初始化校验内容
                if isinstance(case_data["expected_request"], list):
                    # 多个正则表达式校验,遍历校验
                    for i in case_data["expected_request"]:
                        result = re.findall(i.replace("\"", "\'"), str(data))
                        allure.attach('校验完成结果\n', str(result))
                else:
                    # 单个正则表达式
                    result = re.findall(
                        case_data["expected_request"].replace("\"", "\'"),
                        str(data))
                    with allure.step("正则校验"):
                        allure.attach("期望code",
                                      str(case_data["expected_code"]))
                        allure.attach(
                            '正则表达式',
                            str(case_data["expected_request"]).replace(
                                "\'", "\""))
                        allure.attach("实际code", str(code))
                        allure.attach('实际data', str(data))
                        allure.attach(
                            case_data["expected_request"].replace("\"", "\'") +
                            '校验完成结果',
                            str(result).replace("\'", "\""))
                # 未匹配到校验内容
                if not result:
                    success["result"] = False
                    if case_data.get("CustomFail"):
                        info = CustomFail.custom_manage(
                            case_data.get("CustomFail"), relevance)
                        raise failureException(
                            str(info) +
                            "\n正则未校验到内容! %s" % case_data["expected_request"])
                    else:
                        raise failureException("正则未校验到内容! %s" %
                                               case_data["expected_request"])
            # 正则表达式为空时
            except KeyError:
                success["result"] = False
                raise failureException("正则校验执行失败! %s\n正则表达式为空时" %
                                       case_data["expected_request"])
        else:
            success["result"] = False
            raise failureException("http状态码错误!\n %s != %s" %
                                   (code, case_data["expected_code"]))

    # 数据库校验
    elif case_data["check_type"] == "datebase_check":
        pass
    else:
        success["result"] = False
        raise failureException("无该校验方式%s" % case_data["check_type"])
def send_request(data, host, address, relevance, _path, success):
    """
    再次封装请求
    :param data: 测试用例
    :param host: 测试地址
    :param address: 接口地址
    :param relevance: 关联对象
    :param _path: case路径
    :param success: 全局结果
    :return:
    """
    logging.info("=" * 100)
    header = ReadParam.read_param(data["test_name"], data["headers"],
                                  relevance, _path, success)  # 处理请求头
    logging.debug("请求头处理结果:  %s" % header)
    parameter = ReadParam.read_param(data["test_name"], data["parameter"],
                                     relevance, _path, success)  # 处理请求参数
    logging.debug("请求参数处理结果:  %s" % header)
    try:
        # 如果用例中写了host和address,则使用用例中的host和address,若没有则使用全局的
        host = data["host"]
    except KeyError:
        pass
    try:
        address = data["address"]
    except KeyError:
        pass
    host = HostManage.host_manage(host)  # host处理,读取配置文件中的host
    address = ParamManage.manage(address, relevance)
    logging.debug("host处理结果:  %s" % host)
    if not host:
        raise failureException("接口请求地址为空  %s" % data["headers"])
    logging.info("请求接口:%s" % str(data["test_name"]))
    logging.info("请求地址:%s" % data["http_type"] + "://" + host + address)
    logging.info("请求头: %s" % str(header))
    logging.info("请求参数: %s" % str(parameter))
    if data["request_type"].lower() == 'post':
        if data["file"]:
            with allure.step("POST上传文件"):
                allure.attach("请求接口:", str(data["test_name"]))
                allure.attach("请求地址",
                              data["http_type"] + "://" + host + address)
                allure.attach("请求头", str(header))
                allure.attach("请求参数", str(parameter))
            result = confighttp.post(
                header=header,
                address=data["http_type"] + "://" + host + address,
                request_parameter_type=data["parameter_type"],
                files=parameter,
                timeout=data["timeout"])
        else:
            with allure.step("POST请求接口"):
                allure.attach("请求接口:", str(data["test_name"]))
                allure.attach("请求地址",
                              data["http_type"] + "://" + host + address)
                allure.attach("请求头", str(header))
                allure.attach("请求参数", str(parameter))
            logging.info("POST请求接口")
            result = confighttp.post(
                header=header,
                address=data["http_type"] + "://" + host + address,
                request_parameter_type=data["parameter_type"],
                data=parameter,
                timeout=data["timeout"])
    elif data["request_type"].lower() == 'get':
        with allure.step("GET请求接口"):
            allure.attach("请求接口:", str(data["test_name"]))
            allure.attach("请求地址", data["http_type"] + "://" + host + address)
            allure.attach("请求头", str(header))
            allure.attach("请求参数", str(parameter))
        logging.info("GET请求接口")
        result = confighttp.get(header=header,
                                address=data["http_type"] + "://" + host +
                                address,
                                data=parameter,
                                timeout=data["timeout"])
    elif data["request_type"].lower() == "put":
        if data["file"]:
            with allure.step("PUT上传文件"):
                allure.attach("请求接口:", str(data["test_name"]))
                allure.attach("请求地址",
                              data["http_type"] + "://" + host + address)
                allure.attach("请求头", str(header))
                allure.attach("请求参数", str(parameter))
            logging.info("PUT上传文件")
            result = confighttp.put(
                header=header,
                address=data["http_type"] + "://" + host + address,
                request_parameter_type=data["parameter_type"],
                files=parameter,
                timeout=data["timeout"])
        else:
            with allure.step("PUT请求接口"):
                allure.attach("请求接口:", str(data["test_name"]))
                allure.attach("请求地址",
                              data["http_type"] + "://" + host + address)
                allure.attach("请求头", str(header))
                allure.attach("请求参数", str(parameter))
            logging.info("PUT请求接口")
            result = confighttp.put(
                header=header,
                address=data["http_type"] + "://" + host + address,
                request_parameter_type=data["parameter_type"],
                data=parameter,
                timeout=data["timeout"])
    elif data["request_type"].lower() == "delete":
        with allure.step("DELETE请求接口"):
            allure.attach("请求接口:", str(data["test_name"]))
            allure.attach("请求地址", data["http_type"] + "://" + host + address)
            allure.attach("请求头", str(header))
            allure.attach("请求参数", str(parameter))
        logging.info("DELETE请求接口")
        result = confighttp.delete(header=header,
                                   address=data["http_type"] + "://" + host +
                                   address,
                                   data=parameter,
                                   timeout=data["timeout"])
    else:
        result = {"code": False, "data": False}
    logging.info("接口请求结果:\n %s" % str(result))
    return result