コード例 #1
0
ファイル: parser.py プロジェクト: zhenglin12/HttpRunner
def __parse_config(config, project_mapping):
    """ parse testcase/testsuite config, include variables and name.
    """
    # get config variables
    raw_config_variables = config.pop("variables", {})
    raw_config_variables_mapping = utils.ensure_mapping_format(
        raw_config_variables)
    override_variables = utils.deepcopy_dict(
        project_mapping.get("variables", {}))
    functions = project_mapping.get("functions", {})

    # override config variables with passed in variables
    raw_config_variables_mapping.update(override_variables)

    # parse config variables
    parsed_config_variables = {}
    for key, value in raw_config_variables_mapping.items():
        parsed_value = parse_data(value,
                                  raw_config_variables_mapping,
                                  functions,
                                  raise_if_variable_not_found=False)
        parsed_config_variables[key] = parsed_value

    if parsed_config_variables:
        config["variables"] = parsed_config_variables

    # parse config name
    config["name"] = parse_data(config.get("name", ""),
                                parsed_config_variables, functions)

    # parse config base_url
    if "base_url" in config:
        config["base_url"] = parse_data(config["base_url"],
                                        parsed_config_variables, functions)
コード例 #2
0
def __prepare_config(config, project_mapping, session_variables_set=None):
    """ parse testcase/testsuite config.
    """
    # get config variables
    raw_config_variables = config.pop("variables", {})
    raw_config_variables_mapping = utils.ensure_mapping_format(
        raw_config_variables)  # 检查变量格式
    override_variables = utils.deepcopy_dict(
        project_mapping.get("variables", {}))  # deepcopy字典
    functions = project_mapping.get("functions", {})

    # override config variables with passed in variables
    raw_config_variables_mapping.update(override_variables)

    if raw_config_variables_mapping:
        config["variables"] = raw_config_variables_mapping

    check_variables_set = set(raw_config_variables_mapping.keys())
    check_variables_set |= (
        session_variables_set or set()
    )  # check_variables_set = check_variables_set | (session_variables_set or set()) True False  取True,都是False 取Fasle
    prepared_config = prepare_lazy_data(config,
                                        functions,
                                        check_variables_set,
                                        cached=True)
    return prepared_config
コード例 #3
0
def _extend_with_testcase(test_dict, testcase_def_dict):
    """ extend test with testcase definition
        test will merge and override testcase config definition.

    Args:
        test_dict (dict): test block
        testcase_def_dict (dict): testcase definition

    Returns:
        dict: extended test dict.

    """
    # override testcase config variables
    testcase_def_dict["config"].setdefault("variables", {})
    testcase_def_variables = utils.ensure_mapping_format(testcase_def_dict["config"].get("variables", {}))
    testcase_def_variables.update(test_dict.pop("variables", {}))
    testcase_def_dict["config"]["variables"] = testcase_def_variables

    # override base_url, verify
    # priority: testcase config > testsuite tests
    test_base_url = test_dict.pop("base_url", "")
    if not testcase_def_dict["config"].get("base_url"):
        testcase_def_dict["config"]["base_url"] = test_base_url

    test_verify = test_dict.pop("verify", True)
    testcase_def_dict["config"].setdefault("verify", test_verify)

    # override testcase config name, output, etc.
    testcase_def_dict["config"].update(test_dict)

    test_dict.clear()
    test_dict.update(testcase_def_dict)
コード例 #4
0
    def extract_response(self, extractors):
        """ extract value from requests.Response and store in OrderedDict.

        Args:
            extractors (list):

                [
                    {"resp_status_code": "status_code"},
                    {"resp_headers_content_type": "headers.content-type"},
                    {"resp_content": "content"},
                    {"resp_content_person_first_name": "content.person.name.first_name"}
                ]

        Returns:
            OrderDict: variable binds ordered dict

        """
        if not extractors:
            return {}

        logger.log_debug("start to extract from response object.")
        extracted_variables_mapping = OrderedDict()
        extract_binds_order_dict = utils.ensure_mapping_format(extractors)

        for key, field in extract_binds_order_dict.items():
            extracted_variables_mapping[key] = self.extract_field(field)

        return extracted_variables_mapping
コード例 #5
0
    def init_test_variables(self, variables_mapping=None):
        """ init test variables, called when each test(api) starts.
            variables_mapping will be evaluated first.

        Args:
            variables_mapping (dict)
                {
                    "random": "${gen_random_string(5)}",
                    "authorization": "${gen_md5($TOKEN, $data, $random)}",
                    "data": '{"name": "user", "password": "******"}',
                    "TOKEN": "debugtalk",
                }

        """
        variables_mapping = variables_mapping or {}
        variables_mapping = utils.ensure_mapping_format(variables_mapping)
        if "m_encoder" in self.session_variables_mapping.keys(
        ):  # 增加判断,如果全局配置变量存在m_encoder,就删除掉
            self.session_variables_mapping.pop("m_encoder")
        variables_mapping.update(self.session_variables_mapping)
        parsed_variables_mapping = parser.parse_variables_mapping(
            variables_mapping)

        self.test_variables_mapping = {}
        # priority: extracted variable > teststep variable
        self.test_variables_mapping.update(parsed_variables_mapping)
        self.test_variables_mapping.update(self.session_variables_mapping)
コード例 #6
0
ファイル: parser.py プロジェクト: luqingfeng01/pycharm
def parse_lazy_data(content, variables_mapping=None):
    """ parse lazy data with evaluated variables mapping.
        Notice: variables_mapping should not contain any variable or function.
    """
    # TODO: refactor type check
    if content is None or isinstance(content, (numeric_types, bool, type)):
        return content

    elif isinstance(content, LazyString):
        variables_mapping = utils.ensure_mapping_format(variables_mapping
                                                        or {})
        return content.to_value(variables_mapping)

    elif isinstance(content, (list, set, tuple)):
        return [parse_lazy_data(item, variables_mapping) for item in content]

    elif isinstance(content, dict):
        parsed_content = {}
        for key, value in content.items():
            parsed_key = parse_lazy_data(key, variables_mapping)
            parsed_value = parse_lazy_data(value, variables_mapping)
            parsed_content[parsed_key] = parsed_value

        return parsed_content

    return content
コード例 #7
0
ファイル: parser.py プロジェクト: Chankee/AutoTestRunner
def __prepare_config(config, project_mapping, session_variables_set=None):
    """ parse testcase/testsuite config.
    """
    # get config variables
    raw_config_variables = config.pop("variables", {})

    override_variables = utils.deepcopy_dict(project_mapping.get("variables", {}))
    functions = project_mapping.get("functions", {})

    if isinstance(raw_config_variables, basestring) and function_regex_compile.match(
            raw_config_variables):
        # config variables are generated by calling function
        # e.g.
        # "config": {
        #     "name": "basic test with httpbin",
        #     "variables": "${gen_variables()}"
        # }
        raw_config_variables_mapping = parse_lazy_data(
            prepare_lazy_data(raw_config_variables, functions_mapping=functions)
        )
    else:
        raw_config_variables_mapping = utils.ensure_mapping_format(raw_config_variables)

    # override config variables with passed in variables
    raw_config_variables_mapping.update(override_variables)

    if raw_config_variables_mapping:
        config["variables"] = raw_config_variables_mapping

    check_variables_set = set(raw_config_variables_mapping.keys())
    check_variables_set |= (session_variables_set or set())
    prepared_config = prepare_lazy_data(config, functions, check_variables_set, cached=True)
    return prepared_config
コード例 #8
0
 def update_session_variables(self, variables_mapping):
     """ update session with extracted variables mapping.
         these variables are valid in the whole running session.
     """
     variables_mapping = utils.ensure_mapping_format(variables_mapping)
     self.session_variables_mapping.update(variables_mapping)
     self.test_variables_mapping.update(self.session_variables_mapping)
コード例 #9
0
    def init_test_variables(self, variables_mapping=None):
        """ init test variables, called when each test(api) starts.
            init测试变量,在每个测试(api)启动时调用
            variables_mapping will be evaluated first.
            首先计算变量映射

        Args:
            variables_mapping (dict)
                {
                    "random": "${gen_random_string(5)}",
                    "authorization": "${gen_md5($TOKEN, $data, $random)}",
                    "data": '{"name": "user", "password": "******"}',
                    "TOKEN": "debugtalk",
                }

        """
        variables_mapping = variables_mapping or {}
        variables_mapping = utils.ensure_mapping_format(variables_mapping)
        variables_mapping.update(self.session_variables_mapping)
        parsed_variables_mapping = parser.parse_variables_mapping(variables_mapping)

        self.test_variables_mapping = {}
        # priority: extracted variable > teststep variable
        # 优先级:提取的变量 > teststep变量
        self.test_variables_mapping.update(parsed_variables_mapping)
        self.test_variables_mapping.update(self.session_variables_mapping)
コード例 #10
0
ファイル: context.py プロジェクト: zhenglin12/HttpRunner
    def init_test_variables(self, variables_mapping=None):
        """ init test variables, called when each test(api) starts.
            variables_mapping will be evaluated first.

        Args:
            variables_mapping (dict)
                {
                    "random": "${gen_random_string(5)}",
                    "authorization": "${gen_md5($TOKEN, $data, $random)}",
                    "data": '{"name": "user", "password": "******"}',
                    "TOKEN": "debugtalk",
                }

        """
        variables_mapping = variables_mapping or {}
        variables_mapping = utils.ensure_mapping_format(variables_mapping)

        self.test_variables_mapping = {}
        # priority: extracted variable > teststep variable
        self.test_variables_mapping.update(variables_mapping)
        self.test_variables_mapping.update(self.session_variables_mapping)

        for variable_name, variable_value in variables_mapping.items():
            variable_value = self.eval_content(variable_value)
            self.update_test_variables(variable_name, variable_value)
コード例 #11
0
 def test_ensure_mapping_format(self):
     map_list = [
         {"a": 1},
         {"b": 2}
     ]
     ordered_dict = utils.ensure_mapping_format(map_list)
     self.assertIsInstance(ordered_dict, dict)
     self.assertIn("a", ordered_dict)
コード例 #12
0
def parse_parameters(parameters, variables_mapping=None, functions_mapping=None):
    """ parse parameters and generate cartesian product.
        解析参数并生成笛卡尔积

    Args:
        parameters (list) parameters: parameter name and value in list参数(列表)参数:列表中的参数名称和值
            parameter value may be in three types:参数值可以有三种类型
                (1) data list, e.g. ["iOS/10.1", "iOS/10.2", "iOS/10.3"]
                (2) call built-in parameterize function, "${parameterize(account.csv)}"
                (3) call custom function in debugtalk.py, "${gen_app_version()}"

        variables_mapping (dict): variables mapping loaded from testcase config从testcase配置加载的变量映射
        functions_mapping (dict): functions mapping loaded from debugtalk.py函数映射:从debugtalk.py加载的函数映射

    Returns:
        list: cartesian product list笛卡儿产品列表

    Examples:
        >>> parameters = [
            {"user_agent": ["iOS/10.1", "iOS/10.2", "iOS/10.3"]},
            {"username-password": "******"},
            {"app_version": "${gen_app_version()}"}
        ]
        >>> parse_parameters(parameters)

    """
    variables_mapping = variables_mapping or {}
    functions_mapping = functions_mapping or {}
    parsed_parameters_list = []

    parameters = utils.ensure_mapping_format(parameters)  # 确保映射的格式是字典
    for parameter_name, parameter_content in parameters.items():
        parameter_name_list = parameter_name.split("-")

        if isinstance(parameter_content, list):
            # (1) data list
            # e.g. {"app_version": ["2.8.5", "2.8.6"]}
            #       => [{"app_version": "2.8.5", "app_version": "2.8.6"}]
            # e.g. {"username-password": [["user1", "111111"], ["test2", "222222"]}
            #       => [{"username": "******", "password": "******"}, {"username": "******", "password": "******"}]
            parameter_content_list = []
            for parameter_item in parameter_content:
                if not isinstance(parameter_item, (list, tuple)):
                    # "2.8.5" => ["2.8.5"]
                    parameter_item = [parameter_item]

                # ["app_version"], ["2.8.5"] => {"app_version": "2.8.5"}
                # ["username", "password"], ["user1", "111111"] => {"username": "******", "password": "******"}
                parameter_content_dict = dict(zip(parameter_name_list, parameter_item))

                parameter_content_list.append(parameter_content_dict)

        elif:
            parsed_variables_mapping = parse_variables_mapping(
                variables_mapping
            )
    return
コード例 #13
0
 def update_session_variables(self, variables_mapping):
     """ update session with extracted variables mapping.
         用提取的变量映射更新会话
         these variables are valid in the whole running session.
         这些变量在整个运行的会话中是有效的
     """
     variables_mapping = utils.ensure_mapping_format(variables_mapping)
     self.session_variables_mapping.update(variables_mapping)
     self.test_variables_mapping.update(self.session_variables_mapping)
コード例 #14
0
ファイル: parser.py プロジェクト: luqingfeng01/pycharm
def __prepare_testcase_tests(tests,
                             config,
                             project_mapping,
                             session_variables_set=None):
    """ override tests with testcase config variables, base_url and verify.
        test maybe nested testcase.

        variables priority:
        testcase config > testcase test > testcase_def config > testcase_def test > api

        base_url priority:
        testcase test > testcase config > testsuite test > testsuite config > api

        verify priority:
        testcase teststep (api) > testcase config > testsuite config

    Args:
        tests (list):
        config (dict):
        project_mapping (dict):

    """
    config_variables = config.get("variables", {})
    config_base_url = config.get("base_url", "")
    config_verify = config.get("verify", True)
    functions = project_mapping.get("functions", {})

    prepared_testcase_tests = []
    session_variables_set = set(
        config_variables.keys()) | (session_variables_set or set())
    for test_dict in tests:

        teststep_variables_set = {"request", "response"}

        # 1, testcase config => testcase tests
        # override test_dict variables
        test_dict_variables = utils.extend_variables(
            test_dict.pop("variables", {}), config_variables)
        test_dict["variables"] = test_dict_variables

        # base_url & verify: priority test_dict > config
        if (not test_dict.get("base_url")) and config_base_url:
            test_dict["base_url"] = config_base_url

        # unify validators' format
        if "validate" in test_dict:
            ref_raw_validators = test_dict.pop("validate", [])
            test_dict["validate"] = [
                validator.uniform_validator(_validator)
                for _validator in ref_raw_validators
            ]

        if "testcase_def" in test_dict:
            # test_dict is nested testcase

            # pass former teststep's (as a testcase) export value to next teststep
            # Since V2.2.2, `extract` is used to replace `output`,
            # `output` is also kept for compatibility
            if "extract" in test_dict:
                session_variables_set |= set(test_dict["extract"])
            elif "output" in test_dict:
                # kept for compatibility
                session_variables_set |= set(test_dict["output"])

            # 2, testcase test_dict => testcase_def config
            testcase_def = test_dict.pop("testcase_def")
            _extend_with_testcase(test_dict, testcase_def)

            # verify priority: nested testcase config > testcase config
            test_dict["config"].setdefault("verify", config_verify)

            # 3, testcase_def config => testcase_def test_dict
            test_dict = _parse_testcase(test_dict, project_mapping,
                                        session_variables_set)

        elif "api_def" in test_dict:
            # test_dict has API reference
            # 2, test_dict => api
            api_def_dict = test_dict.pop("api_def")
            _extend_with_api(test_dict, api_def_dict)

        # current teststep variables
        teststep_variables_set |= set(test_dict.get("variables", {}).keys())

        # verify priority: testcase teststep > testcase config
        if "request" in test_dict and "verify" not in test_dict["request"]:
            test_dict["request"]["verify"] = config_verify

        # move extracted variable to session variables
        if "extract" in test_dict:
            extract_mapping = utils.ensure_mapping_format(test_dict["extract"])
            session_variables_set |= set(extract_mapping.keys())

        teststep_variables_set |= session_variables_set

        # convert validators to lazy function
        validators = test_dict.pop("validate", [])
        prepared_validators = []
        for _validator in validators:
            function_meta = {
                "func_name": _validator["comparator"],
                "args": [_validator["check"], _validator["expect"]],
                "kwargs": {}
            }
            prepared_validators.append(
                LazyFunction(function_meta, functions, teststep_variables_set))
        test_dict["validate"] = prepared_validators

        # convert variables and functions to lazy object.
        # raises VariableNotFound if undefined variable exists in test_dict
        prepared_test_dict = prepare_lazy_data(test_dict, functions,
                                               teststep_variables_set)
        prepared_testcase_tests.append(prepared_test_dict)

    return prepared_testcase_tests
コード例 #15
0
ファイル: parser.py プロジェクト: luqingfeng01/pycharm
def parse_parameters(parameters,
                     variables_mapping=None,
                     functions_mapping=None):
    """ parse parameters and generate cartesian product.

    Args:
        parameters (list) parameters: parameter name and value in list
            parameter value may be in three types:
                (1) data list, e.g. ["iOS/10.1", "iOS/10.2", "iOS/10.3"]
                (2) call built-in parameterize function, "${parameterize(account.csv)}"
                (3) call custom function in debugtalk.py, "${gen_app_version()}"

        variables_mapping (dict): variables mapping loaded from testcase config
        functions_mapping (dict): functions mapping loaded from debugtalk.py

    Returns:
        list: cartesian product list

    Examples:
        >>> parameters = [
            {"user_agent": ["iOS/10.1", "iOS/10.2", "iOS/10.3"]},
            {"username-password": "******"},
            {"app_version": "${gen_app_version()}"}
        ]
        >>> parse_parameters(parameters)

    """
    variables_mapping = variables_mapping or {}
    functions_mapping = functions_mapping or {}
    parsed_parameters_list = []

    parameters = utils.ensure_mapping_format(parameters)
    for parameter_name, parameter_content in parameters.items():
        parameter_name_list = parameter_name.split("-")

        if isinstance(parameter_content, list):
            # (1) data list
            # e.g. {"app_version": ["2.8.5", "2.8.6"]}
            #       => [{"app_version": "2.8.5", "app_version": "2.8.6"}]
            # e.g. {"username-password": [["user1", "111111"], ["test2", "222222"]}
            #       => [{"username": "******", "password": "******"}, {"username": "******", "password": "******"}]
            parameter_content_list = []
            for parameter_item in parameter_content:
                if not isinstance(parameter_item, (list, tuple)):
                    # "2.8.5" => ["2.8.5"]
                    parameter_item = [parameter_item]

                # ["app_version"], ["2.8.5"] => {"app_version": "2.8.5"}
                # ["username", "password"], ["user1", "111111"] => {"username": "******", "password": "******"}
                parameter_content_dict = dict(
                    zip(parameter_name_list, parameter_item))

                parameter_content_list.append(parameter_content_dict)
        else:
            # (2) & (3)
            parsed_variables_mapping = parse_variables_mapping(
                variables_mapping)
            parsed_parameter_content = eval_lazy_data(
                parameter_content, parsed_variables_mapping, functions_mapping)
            if not isinstance(parsed_parameter_content, list):
                raise exceptions.ParamsError("parameters syntax error!")

            parameter_content_list = []
            for parameter_item in parsed_parameter_content:
                if isinstance(parameter_item, dict):
                    # get subset by parameter name
                    # {"app_version": "${gen_app_version()}"}
                    # gen_app_version() => [{'app_version': '2.8.5'}, {'app_version': '2.8.6'}]
                    # {"username-password": "******"}
                    # get_account() => [
                    #       {"username": "******", "password": "******"},
                    #       {"username": "******", "password": "******"}
                    # ]
                    parameter_dict = {
                        key: parameter_item[key]
                        for key in parameter_name_list
                    }
                elif isinstance(parameter_item, (list, tuple)):
                    # {"username-password": "******"}
                    # get_account() => [("user1", "111111"), ("user2", "222222")]
                    parameter_dict = dict(
                        zip(parameter_name_list, parameter_item))
                elif len(parameter_name_list) == 1:
                    # {"user_agent": "${get_user_agent()}"}
                    # get_user_agent() => ["iOS/10.1", "iOS/10.2"]
                    parameter_dict = {parameter_name_list[0]: parameter_item}

                parameter_content_list.append(parameter_dict)

        parsed_parameters_list.append(parameter_content_list)

    return utils.gen_cartesian_product(*parsed_parameters_list)
コード例 #16
0
 def __init__(self, variables=None):
     variables_mapping = utils.ensure_mapping_format(variables or {})
     self.session_variables_mapping = parser.parse_variables_mapping(
         variables_mapping)
     self.test_variables_mapping = {}
     self.init_test_variables()
コード例 #17
0
def parse_data(content, variables_mapping=None, functions_mapping=None, raise_if_variable_not_found=True):
    """ parse content with variables mapping

    Args:
        content (str/dict/list/numeric/bool/type): content to be parsed
        variables_mapping (dict): variables mapping.
        functions_mapping (dict): functions mapping.
        raise_if_variable_not_found (bool): if set False, exception will not raise when VariableNotFound occurred.

    Returns:
        parsed content.

    Examples:
        >>> content = {
                'request': {
                    'url': '/api/users/$uid',
                    'headers': {'token': '$token'}
                }
            }
        >>> variables_mapping = {"uid": 1000, "token": "abcdef"}
        >>> parse_data(content, variables_mapping)
            {
                'request': {
                    'url': '/api/users/1000',
                    'headers': {'token': 'abcdef'}
                }
            }

    """
    # TODO: refactor type check
    if content is None or isinstance(content, (numeric_types, bool, type)):
        return content

    if isinstance(content, (list, set, tuple)):
        return [
            parse_data(
                item,
                variables_mapping,
                functions_mapping,
                raise_if_variable_not_found
            )
            for item in content
        ]

    if isinstance(content, dict):
        parsed_content = {}
        for key, value in content.items():
            parsed_key = parse_data(
                key,
                variables_mapping,
                functions_mapping,
                raise_if_variable_not_found
            )
            parsed_value = parse_data(
                value,
                variables_mapping,
                functions_mapping,
                raise_if_variable_not_found
            )
            parsed_content[parsed_key] = parsed_value
            if extract_variables(parsed_value) == [] and extract_functions(parsed_value) == []:
                variables_mapping[parsed_key] = parsed_value

        return parsed_content

    if isinstance(content, basestring):
        # content is in string format here
        variables_mapping = utils.ensure_mapping_format(variables_mapping or {})
        functions_mapping = functions_mapping or {}
        content = content.strip()

        try:
            # replace functions with evaluated value
            # Notice: parse_string_functions must be called before parse_string_variables
            content = parse_string_functions(
                content,
                variables_mapping,
                functions_mapping
            )
            if extract_functions(content) != []:
                content = parse_data(content, variables_mapping, functions_mapping)

            # replace variables with binding value
            content = parse_string_variables(
                content,
                variables_mapping,
                functions_mapping
            )
        except exceptions.VariableNotFound:
            if raise_if_variable_not_found:
                raise

    return content
コード例 #18
0
ファイル: context.py プロジェクト: zhenglin12/HttpRunner
 def __init__(self, functions, variables=None):
     self.session_variables_mapping = utils.ensure_mapping_format(variables
                                                                  or {})
     self.FUNCTIONS_MAPPING = functions
     self.init_test_variables()
     self.validation_results = []