Example #1
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
Example #2
0
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
Example #3
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)
Example #4
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

    # override name
    test_name = test_dict.pop("name", None) \
        or testcase_def_dict["config"].pop("name", None) \
        or "testcase name undefined"

    # merge & override setup_hooks and teardown_hooks
    def_teardown_hooks = testcase_def_dict["config"].pop("teardown_hooks", [])
    ref_teardown_hooks = test_dict.pop("teardown_hooks", [])
    extended_teardown_hooks = def_teardown_hooks + ref_teardown_hooks
    if extended_teardown_hooks:
        testcase_def_dict["config"]["teardown_hooks"] = extended_teardown_hooks
    def_setup_hooks = testcase_def_dict["config"].pop("setup_hooks", [])
    ref_setup_hooks = test_dict.pop("setup_hooks", [])
    extended_setup_hooks = ref_setup_hooks + def_setup_hooks
    if extended_setup_hooks:
        testcase_def_dict["config"]["setup_hooks"] = extended_setup_hooks

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

    test_dict.clear()
    test_dict.update(testcase_def_dict)
Example #5
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("env", {}))
    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())
    prepared_config = prepare_lazy_data(config,
                                        functions,
                                        check_variables_set,
                                        cached=True)
    return prepared_config
Example #6
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)
        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)
Example #7
0
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):

    """
    global temp_extracted_set
    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()) | temp_extracted_set
    for test_dict in tests:

        teststep_variables_set = {"request", "response"}

        # 1, testcase config => testcase tests
        # override test_dict variables
        config_variables_tmp = utils.deepcopy_dict(config_variables)
        test_dict_variables = utils.extend_variables(
            config_variables_tmp, test_dict.pop("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

            if "output" in test_dict:
                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 test_dict.get("extract", {}):
            extract_mapping = utils.ensure_mapping_format(test_dict["extract"])
            session_variables_set |= set(extract_mapping.keys())
            temp_extracted_set |= session_variables_set

        session_variables_set |= temp_extracted_set
        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
Example #8
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
        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)
    cartesian = parameters.pop('cartesian', None)
    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)
    if cartesian:
        return utils.gen_cartesian_product(*parsed_parameters_list)
    else:
        return utils.gen_dict_from_zip(*parsed_parameters_list)
Example #9
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.init_test_variables()
     self.validation_results = []
Example #10
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)