Exemple #1
0
class Testtest:
    ComLog().use_log()
    yaml_path = ComConfig().test_params_path()
    # 获取指定测试用例的用例信息
    test_params = ComParams().test_params(yaml_path, yaml_name="test.yml")

    @allure.title("{title}")
    @pytest.mark.parametrize("param, title", test_params)
    def test_login(self, param, title):
        result = ComManage().assert_manner(param)
        assert result
Exemple #2
0
class ComYaml:

    ComLog().use_log()

    @staticmethod
    def __read_yaml(yaml_path):
        """
        读取yaml文件
        :param yaml_path: yaml文件路径
        :return: {}
        """
        try:
            dict_data = yaml.load(open(yaml_path, 'r', encoding="utf-8"),
                                  Loader=yaml.FullLoader)
            return dict_data
        except Exception as es:
            logging.error(F'读取{yaml_path}文件出错,错误是{es}')
            raise (F'读取{yaml_path}文件出错,错误是{es}')

    def read_yaml(self, yml_path):
        """
        遍历文件夹下的所有yaml文件,拆分其中的dec和parameters,并设置为字典的键值对,返回字典
        :param yml_path: yaml文件路径 或 yaml文件路径
        :return: {dec1:parameters1, dec2:parameters2}
        """
        values_dict = {}
        # 判断路径是否是文件夹、获取该文件夹下所有的yml文件、并遍历
        try:
            if Path(yml_path).is_dir():
                for file in [x for x in list(Path(yml_path).glob("**/*.yml"))]:
                    data_dict = self.__read_yaml(file)
                    for test_name, parameters in data_dict.items():
                        values_dict[test_name] = parameters
            elif str(yml_path).endswith(".yml"):
                file = yml_path  # 为了log服务才这样赋值的
                data_dict = self.__read_yaml(file)
                for test_name, parameters in data_dict.items():
                    values_dict[test_name] = parameters
        except Exception as es:
            logging.error(F"解析{file}文件内容出错,错误是{es}")
            raise Exception
        return values_dict
Exemple #3
0
 def __init__(self):
     ComLog().use_log()
Exemple #4
0
"""

import requests
import json
import logging
from common.com_log import ComLog
import urllib3
import allure
"""
requests常用方法
只支持http/https,以及get、post请求
"""

# 忽略InsecureRequestWarning
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
ComLog().use_log()


class ComRequest:
    req_session = requests.session()

    def send_request(self, request_data):
        global response
        try:
            self.url = request_data["url"].strip()
        except Exception as es:
            logging.error(F"请求数据的url获取失败,请求数据是:{request_data},错误是{es}")
            raise (F"请求数据的url获取失败,请求数据是:{request_data},错误是{es}")

        try:
            method = request_data["method"]
Exemple #5
0
class ComAssert:
    ComLog().use_log()

    def eq(self, ex, re):
        try:
            assert str(ex) == str(re)
            return True
        except Exception as es:
            logging.error(F"eq判断失败,预期结果:{ex},实际结果:{re}")
            raise (F"eq相等判断失败,预期结果:{ex},实际结果:{re}")

    def contains(self, ex, re):
        try:
            assert str(ex) in str(re)
            return True
        except Exception as es:
            logging.error(F"contains判断失败,预期结果:{ex},实际结果:{re}")
            raise (F"contains判断失败,预期结果:{ex},实际结果:{re}")

    def not_contains(self, ex, re):
        try:
            assert str(ex) not in str(re)
            return True
        except Exception as es:
            logging.error(F"not_contains判断失败,预期结果:{ex},实际结果:{re}")
            raise (F"not_contains判断失败,预期结果:{ex},实际结果:{re}")

    def lt(self, ex, re):
        try:
            if isinstance(re, int) or isinstance(re, float):
                assert float(ex) < float(re)
            else:
                assert float(ex) < float(len(re))
            return True
        except Exception as es:
            logging.error(F"lt判断失败,预期结果:{ex},实际结果:{re}")
            raise (F"lt判断失败,预期结果:{ex},实际结果:{re}")

    def le(self, ex, re):
        try:
            # assert float(ex) <= float(re)
            if isinstance(re, int) or isinstance(re, float):
                assert float(ex) <= float(re)
            else:
                assert float(ex) <= float(len(re))
            return True
        except Exception as es:
            logging.error(F"le判断失败,预期结果:{ex},实际结果:{re}")
            raise (F"le判断失败,预期结果:{ex},实际结果:{re}")

    def gt(self, ex, re):
        try:
            # assert float(ex) > float(re)
            if isinstance(re, int) or isinstance(re, float):
                assert float(ex) > float(re)
            else:
                assert float(ex) > float(len(re))
            return True
        except Exception as es:
            logging.error(F"gt判断失败,预期结果:{ex},实际结果:{re}")
            raise (F"gt判断失败,预期结果:{ex},实际结果:{re}")

    def ge(self, ex, re):
        try:
            # assert float(ex) >= float(re)
            if isinstance(re, int) or isinstance(re, float):
                assert float(ex) >= float(re)
            else:
                assert float(ex) >= float(len(re))
            return True
        except Exception as es:
            logging.error(F"ge判断失败,预期结果:{ex},实际结果:{re}")
            raise (F"ge判断失败,预期结果:{ex},实际结果:{re}")

    def sw(self, ex, re):
        try:
            assert str(ex).startswith(str(re))
            return True
        except Exception as es:
            logging.error(F"sw判断失败,预期结果:{ex},不以{re}开头")
            raise (F"sw判断失败,预期结果:{ex},不以{re}开头")

    def ew(self, ex, re):
        try:
            assert str(ex).endswith(str(re))
            return True
        except Exception as es:
            logging.error(F"ew判断失败,预期结果:{ex},不以{re}结尾")
            raise (F"ew判断失败,预期结果:{ex},不以{re}结尾")

    def assert_result(self, assert_type, ex, re):
        """
        根据判断类型调用对应的判断方法
        :param assert_type:
        :param ex:
        :param re:
        :return:
        """
        try:
            if assert_type == "eq":
                return self.eq(ex, re)
            elif assert_type == "contains":
                return self.contains(ex, re)
            elif assert_type == "not_contains":
                return self.not_contains(ex, re)
            elif assert_type == "lt":
                return self.lt(ex, re)
            elif assert_type == "not_contains":
                return self.not_contains(ex, re)
            elif assert_type == "le":
                return self.le(ex, re)
            elif assert_type == "gt":
                return self.gt(ex, re)
            elif assert_type == "ge":
                return self.ge(ex, re)
            elif assert_type == "sw":
                return self.sw(ex, re)
            elif assert_type == "ew":
                return self.ew(ex, re)
        except Exception as es:
            logging.error(F"出现了非法的比较类型或者比较结果False:{assert_type}")
            raise (F"出现了非法的比较类型或者比较结果False:{assert_type}")

    def assert_code(self, assert_type, ex, response):
        """
        判断response.status_code是否如预期
        :param assert_type:
        :param ex:
        :param response:
        :return:
        """
        try:
            ex_code = ex[1]
            re_code = response.status_code
            return self.assert_result(assert_type, ex_code, re_code)
        except Exception as es:
            logging.error(
                F"code判断失败,判断类型是{assert_type}, 预期值:{ex_code}, 实际值:{re_code}")
            raise (
                F"code判断失败,判断类型是{assert_type}, 预期值:{ex_code}, 实际值:{re_code}")

    def assert_headers(self, assert_type, ex_value, response):
        """
        判断headers的内容是否如预期
        :param assert_type:
        :param ex_value:
        :param response:
        :return:
        """
        try:
            ex_headers = ex_value[1]
            headers_key = str(ex_value[0]).split(".")[1]
            re_headers = response.headers[headers_key]
            return self.assert_result(assert_type, ex_headers, re_headers)
        except Exception as es:
            logging.error(
                F"headers判断失败,判断类型是{assert_type}, 预期值:{ex_headers}, headers的key是:{headers_key},实际值:{re_headers}"
            )
            raise (
                F"headers判断失败,判断类型是{assert_type}, 预期值:{ex_headers}, headers的key是:{headers_key},实际值:{re_headers}"
            )

    @staticmethod
    def dict_value(key, data):
        """
        根据key层级获取data对应的value;jsonpath_rw的方法也可以实现(jsonpath-rw无法安装时用)
        :param key: str:"one.two.three..."
        :param data: dict
        :return:
        """

        key_list = str(key).split(".")
        for now_key in key_list:
            if len(key_list) == 1:
                value = data[now_key]
                return value
            else:
                new_data = data[now_key]
                key = str.join(".", key_list[1:])
                return ComAssert.dict_value(key, new_data)  # 递归别忘了返回

    def assert_content(self, assert_type, ex_value, response):
        """
        判断content的内容是否如预期
        :param assert_type:
        :param ex_value:
        :param response:
        :return:
        """
        try:
            # 把"content.xx.yy"转成["xx.yy"]再转成"xx.yy"
            keys = str(ex_value[0].split("content.")[1:][0])
            ex_content = ex_value[1]

            json_content = json.loads(response.content)  # byte转dict
            # jsonpath_rw,根据key("xx.yy.zz"),返回dict中该key的值
            re_content = [
                match.value for match in parse(str(keys)).find(json_content)
            ][0]
            return self.assert_result(assert_type, ex_content, re_content)
        except Exception as es:
            logging.error(
                F"content判断失败或者响应文本不是json格式,判断类型是{assert_type}, 预期值:{ex_content}, content的key是:{keys},实际值:{re_content}"
            )
            raise (
                F"content判断失败或者响应文本不是json格式,判断类型是{assert_type}, 预期值:{ex_content}, content的key是:{keys},实际值:{re_content}"
            )
Exemple #6
0
class ComManage:
    ComLog().use_log()

    def __init__(self):
        self.com_assert = ComAssert()
        self.config = ComConfig()
        self.com_params = ComParams()

    def validate_manner(self, validates_dict):
        """
        处理用例数据中的validates数据
        :param validates_dict:
        :return:
        """
        try:
            ex_dict = dict()

            # 类型
            eq_list = []  # 相等
            contains_list = []  # 包含
            not_contains_list = []  # 不包含
            lt_list = []  # 小于
            le_list = []  # 小于等于
            gt_list = []  # 大于
            ge_list = []  # 大于等于
            sw_list = []  # 以xx开头
            ew_list = []  # 以xx结尾

            for validate in eval(validates_dict):
                if "eq" in validate:
                    eq_list.append(validate["eq"])
                elif "contains" in validate:
                    contains_list.append(validate["contains"])
                elif "not_contains" in validate:
                    not_contains_list.append(validate["not_contains"])
                elif "lt" in validate:
                    lt_list.append(validate["lt"])
                elif "le" in validate:
                    le_list.append(validate["le"])
                elif "gt" in validate:
                    gt_list.append(validate["gt"])
                elif "ge" in validate:
                    ge_list.append(validate["ge"])
                elif "sw" in validate:
                    sw_list.append(validate["sw"])
                elif "ew" in validate:
                    ew_list.append(validate["ew"])

            ex_dict["eq"] = eq_list
            ex_dict["contains"] = contains_list
            ex_dict["not_contains"] = not_contains_list
            ex_dict["lt"] = lt_list
            ex_dict["le"] = le_list
            ex_dict["gt"] = gt_list
            ex_dict["ge"] = ge_list
            ex_dict["sw"] = sw_list
            ex_dict["ew"] = ew_list

            return ex_dict

        except Exception as es:
            logging.error(F"解析validate数据失败,数据为:{validates_dict}")
            raise es

    def request_manner(self, request_dict):
        """
        发送请求,同时处理依赖数据:

        处理variables、variables_data、relevance
        执行variables对应的用例,返回响应中relevance对应的值,并赋值给variables_data
        替换测试用例parameters中对应的variables_data。然后返回处理过后的parameters

        1:先确定需要执行的用例yml中的请求(因为一个yml会存在多个请求内容)
        2:判断variables_data的值,在对应用例的param中的relevance的value,
        3:再从该用例响应中提取出来
        4:接着替换掉之前的测试用例parameters中对应的variables_data。然后返回处理过后的parameters

        :param request_dict:
        :return:
        """
        # variables: [{'login': ['basic_id', 'audid']}, {'Basic': ['test_id']}]
        # variables_data: ['audid', 'basic_id']
        # relevance: {'id': 'content.data'}

        try:
            if "variables" in request_dict and "variables_data" in request_dict:

                # 处理variables的内容,去掉$,方便处理
                variables_data = request_dict["variables_data"]
                variables = request_dict["variables"]
                yaml_path = self.config.test_params_path()

                for variable in eval(variables):
                    # 获取依赖数据的值
                    for test_name in variable:
                        # print(F"variablesss:{variable}")
                        yaml_name = str(test_name) + ".yml"
                        variables_value = self.variables_value(
                            yaml_path, yaml_name, variables_data)
                # 把依赖数据变量替换依赖数据的值
                request_dict = self.com_params.replace_request(
                    request_dict, variables_value)
            response = ComRequest().send_request(request_dict)
            return response
        except Exception as e:
            logging.error(F"请求发送失败,请求信息是:{request_dict}")
            raise (F"请求发送失败,请求信息是:{request_dict}")

    # 因为调用了Mannage类的的方法,两个类之间不能互相调用,所以移来这里
    def variables_value(self, yaml_path, yaml_name, variables_data):
        """
        获取依赖数据的值。比如
        variables: [{'login': ['data_value', 'code_value']}, {'Basic': ['test_id']}]
        variables_data: ['data_value', 'code_value']
        relevance: {'data_value': 'content.data', 'code_value': 'content.code'}
        根据variables,到对应的测试用例yaml(key)中,获取到其中拥有
        和variables的value全部一致的relevance的key的测试用例信息
        然后执行该测试用例,根据relevance的value,到respon中获取对应的值(依赖测试数据的值)
        :param yaml_path:
        :param yaml_name:
        :param variables_data:
        :return:
        """
        try:
            tests_params = ComParams().test_params(
                yaml_path, yaml_name)[0]  # 获取到想要执行用例yml的所有内容
            num = 0  # 记录依赖测试用例的请求执行次数,只需要执行一次即可
            for test_params in tests_params:
                if "relevance" in test_params:  # 判断存在relevance的请求信息内容
                    relevance_data = test_params["relevance"]
                    variables_value = []

                    if self.com_params.list_in_dict(
                            variables_data, eval(
                                relevance_data)):  # 获取有全部variables_data的请求信息内容
                        response = ComManage().request_manner(test_params)
                        num += 1
                        for variable_key in variables_data:
                            # 在relevance_data中,获取variables_data的key对应的value
                            variable_dict = self.com_params.relevance_value(
                                variable_key,
                                eval(relevance_data)[variable_key], response)
                            variables_value.append(variable_dict)
                    if num >= 1:
                        return variables_value
        except Exception as es:
            logging.error(F"被依赖用例{yaml_name}不存在依赖用例所需的依赖数据:{variables_data}")
            raise (F"被依赖用例{yaml_name}不存在依赖用例所需的依赖数据:{variables_data}")

    def assert_manner(self, request_dict):
        """
        根据测试用例的validate部分的判断类型(content/headers/status_code),调用不同的判断方法
        :param request_dict:
        :return: 全通过则返回True
        """
        try:
            # params = request_dict[0][0]
            # ex_validates = self.validate_manner(params["validate"])
            # response = self.request_manner(params)

            ex_validates = self.validate_manner(request_dict["validate"])
            response = self.request_manner(request_dict)

            for key in ex_validates:
                values = ex_validates[key]

                if len(values) >= 1:
                    asssert_type = key
                    for value in values:
                        value_start = value[0].split(".")[0]
                        if value_start.startswith("status_code"):
                            assert self.com_assert.assert_code(
                                asssert_type, value, response)
                        elif value_start.startswith("headers"):
                            assert self.com_assert.assert_headers(
                                asssert_type, value, response)
                        elif value_start.startswith("content"):
                            assert self.com_assert.assert_content(
                                asssert_type, value, response)
            return True

        except Exception as es:
            logging.error(F"异常判断类型:{key},判断值是{value},响应数据是{response.content}")
            raise (F"异常判断类型:{key},判断值是{value},响应数据是{response.content}")
Exemple #7
0
 def __init__(self):
     ComLog().use_log()
     # 报告文件文件夹,防止生成的报告内容叠加
     self.time = time.strftime('%m-%d-%H-%M', time.localtime())
     self.report_path = ComConfig().get_report_path()