def __parse_testcase_tests(tests, config, project_mapping): """ 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/verify priority: testcase test > testcase config > testsuite test > testsuite config > api Args: tests (list): config (dict): project_mapping (dict): """ config_variables = config.pop("variables", {}) config_base_url = config.pop("base_url", "") config_verify = config.pop("verify", True) functions = project_mapping.get("functions", {}) for test_dict in tests: # 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 test_dict.setdefault("verify", config_verify) # 1, testcase config => testcase tests # override test_dict variables test_dict["variables"] = utils.extend_variables( test_dict.pop("variables", {}), config_variables ) test_dict["variables"] = parse_data( test_dict["variables"], test_dict["variables"], functions, raise_if_variable_not_found=False ) # parse test_dict name test_dict["name"] = parse_data( test_dict.pop("name", ""), test_dict["variables"], functions, raise_if_variable_not_found=False ) if "testcase_def" in test_dict: # test_dict is nested testcase # 2, testcase test_dict => testcase_def config testcase_def = test_dict.pop("testcase_def") _extend_with_testcase(test_dict, testcase_def) # 3, testcase_def config => testcase_def test_dict _parse_testcase(test_dict, project_mapping) else: if "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) if test_dict.get("base_url"): # parse base_url base_url = parse_data( test_dict.pop("base_url"), test_dict["variables"], functions ) # build path with base_url # variable in current url maybe extracted from former api request_url = parse_data( test_dict["request"]["url"], test_dict["variables"], functions, raise_if_variable_not_found=False ) test_dict["request"]["url"] = utils.build_url( base_url, request_url )
def _extend_with_api(test_dict, api_def_dict): """ extend test with api definition, test will merge and override api definition. Args: test_dict (dict): test block api_def_dict (dict): api definition Returns: dict: extended test dict. Examples: >>> api_def_dict = { "name": "get token 1", "request": {...}, "validate": [{'eq': ['status_code', 200]}] } >>> test_dict = { "name": "get token 2", "extract": {"token": "content.token"}, "validate": [{'eq': ['status_code', 201]}, {'len_eq': ['content.token', 16]}] } >>> _extend_with_api(test_dict, api_def_dict) { "name": "get token 2", "request": {...}, "extract": {"token": "content.token"}, "validate": [{'eq': ['status_code', 201]}, {'len_eq': ['content.token', 16]}] } """ # override name api_def_name = api_def_dict.pop("name", "") test_dict["name"] = test_dict.get("name") or api_def_name # override variables def_variables = api_def_dict.pop("variables", []) test_dict["variables"] = utils.extend_variables( def_variables, test_dict.get("variables", {}) ) # merge & override validators TODO: relocate def_raw_validators = api_def_dict.pop("validate", []) ref_raw_validators = test_dict.get("validate", []) def_validators = [ parse_validator(validator) for validator in def_raw_validators ] ref_validators = [ parse_validator(validator) for validator in ref_raw_validators ] test_dict["validate"] = utils.extend_validators( def_validators, ref_validators ) # merge & override extractors def_extrators = api_def_dict.pop("extract", {}) test_dict["extract"] = utils.extend_variables( def_extrators, test_dict.get("extract", {}) ) # TODO: merge & override request test_dict["request"] = api_def_dict.pop("request", {}) # base_url & verify: priority api_def_dict > test_dict if api_def_dict.get("base_url"): test_dict["base_url"] = api_def_dict["base_url"] if "verify" in api_def_dict: test_dict["request"]["verify"] = api_def_dict["verify"] # merge & override setup_hooks def_setup_hooks = api_def_dict.pop("setup_hooks", []) ref_setup_hooks = test_dict.get("setup_hooks", []) extended_setup_hooks = list(set(def_setup_hooks + ref_setup_hooks)) if extended_setup_hooks: test_dict["setup_hooks"] = extended_setup_hooks # merge & override teardown_hooks def_teardown_hooks = api_def_dict.pop("teardown_hooks", []) ref_teardown_hooks = test_dict.get("teardown_hooks", []) extended_teardown_hooks = list(set(def_teardown_hooks + ref_teardown_hooks)) if extended_teardown_hooks: test_dict["teardown_hooks"] = extended_teardown_hooks # TODO: extend with other api definition items, e.g. times test_dict.update(api_def_dict) return test_dict
def __get_parsed_testsuite_testcases(testcases, testsuite_config, project_mapping): """ override testscases with testsuite config variables, base_url and verify. variables priority: parameters > testsuite config > testcase config > testcase_def config > testcase_def tests > api base_url priority: testcase_def tests > testcase_def config > testcase config > testsuite config Args: testcases (dict): { "testcase1 name": { "testcase": "testcases/create_and_check.yml", "weight": 2, "variables": { "uid": 1000 }, "parameters": { "uid": [100, 101, 102] }, "testcase_def": { "config": {}, "teststeps": [] } }, "testcase2 name": {} } testsuite_config (dict): { "name": "testsuite name", "variables": { "device_sn": "${gen_random_string(15)}" }, "base_url": "http://127.0.0.1:5000" } project_mapping (dict): { "env": {}, "functions": {} } """ testsuite_base_url = testsuite_config.get("base_url") testsuite_config_variables = testsuite_config.get("variables", {}) functions = project_mapping.get("functions", {}) parsed_testcase_list = [] for testcase_name, testcase in testcases.items(): parsed_testcase = testcase.pop("testcase_def") parsed_testcase.setdefault("config", {}) parsed_testcase["path"] = testcase["testcase"] parsed_testcase["config"]["name"] = testcase_name if "weight" in testcase: parsed_testcase["config"]["weight"] = testcase["weight"] # base_url priority: testcase config > testsuite config parsed_testcase["config"].setdefault("base_url", testsuite_base_url) # 1, testsuite config => testcase config # override test_dict variables testcase_config_variables = utils.extend_variables( testcase.pop("variables", {}), testsuite_config_variables ) # 2, testcase config > testcase_def config # override testcase_def config variables parsed_testcase_config_variables = utils.extend_variables( parsed_testcase["config"].pop("variables", {}), testcase_config_variables ) # parse config variables parsed_config_variables = {} for key in parsed_testcase_config_variables: try: parsed_value = parse_data( parsed_testcase_config_variables[key], parsed_testcase_config_variables, functions ) except exceptions.VariableNotFound: pass parsed_testcase_config_variables[key] = parsed_value parsed_config_variables[key] = parsed_value if parsed_config_variables: parsed_testcase["config"]["variables"] = parsed_config_variables # parse parameters if "parameters" in testcase and testcase["parameters"]: cartesian_product_parameters = parse_parameters( testcase["parameters"], parsed_config_variables, functions ) for parameter_variables in cartesian_product_parameters: # deepcopy to avoid influence between parameters parsed_testcase_copied = utils.deepcopy_dict(parsed_testcase) parsed_config_variables_copied = utils.deepcopy_dict(parsed_config_variables) parsed_testcase_copied["config"]["variables"] = utils.extend_variables( parsed_config_variables_copied, parameter_variables ) _parse_testcase(parsed_testcase_copied, project_mapping) parsed_testcase_list.append(parsed_testcase_copied) else: _parse_testcase(parsed_testcase, project_mapping) parsed_testcase_list.append(parsed_testcase) return parsed_testcase_list
def _extend_with_api(test_dict, api_def_dict): """ extend test with api definition, test will merge and override api definition. Args: test_dict (dict): test block, this will override api_def_dict api_def_dict (dict): api definition Examples: >>> api_def_dict = { "name": "get token 1", "request": {...}, "validate": [{'eq': ['status_code', 200]}] } >>> test_dict = { "name": "get token 2", "extract": {"token": "content.token"}, "validate": [{'eq': ['status_code', 201]}, {'len_eq': ['content.token', 16]}] } >>> _extend_with_api(test_dict, api_def_dict) >>> print(test_dict) { "name": "get token 2", "request": {...}, "extract": {"token": "content.token"}, "validate": [{'eq': ['status_code', 201]}, {'len_eq': ['content.token', 16]}] } """ # override api name test_dict.setdefault("name", api_def_dict.pop("name", "api name undefined")) # override variables def_variables = api_def_dict.pop("variables", []) test_dict["variables"] = utils.extend_variables( def_variables, test_dict.get("variables", {})) # merge & override validators TODO: relocate def_raw_validators = api_def_dict.pop("validate", []) def_validators = [ uniform_validator(_validator) for _validator in def_raw_validators ] ref_validators = test_dict.pop("validate", []) test_dict["validate"] = extend_validators(def_validators, ref_validators) # merge & override extractors def_extrators = api_def_dict.pop("extract", {}) test_dict["extract"] = utils.extend_variables(def_extrators, test_dict.get("extract", {})) # merge & override request test_dict["request"] = api_def_dict.pop("request", {}) # base_url & verify: priority api_def_dict > test_dict if api_def_dict.get("base_url"): test_dict["base_url"] = api_def_dict["base_url"] if "verify" in api_def_dict: test_dict["request"]["verify"] = api_def_dict["verify"] # merge & override setup_hooks def_setup_hooks = api_def_dict.pop("setup_hooks", []) ref_setup_hooks = test_dict.get("setup_hooks", []) extended_setup_hooks_tmp = def_setup_hooks + ref_setup_hooks extended_setup_hooks = list(set(extended_setup_hooks_tmp)) extended_setup_hooks.sort(key=extended_setup_hooks_tmp.index) if extended_setup_hooks: test_dict["setup_hooks"] = extended_setup_hooks # merge & override teardown_hooks def_teardown_hooks = api_def_dict.pop("teardown_hooks", []) ref_teardown_hooks = test_dict.get("teardown_hooks", []) extended_teardown_hooks_tmp = def_teardown_hooks + ref_teardown_hooks extended_teardown_hooks = list(set(extended_teardown_hooks_tmp)) extended_teardown_hooks.sort(key=extended_teardown_hooks_tmp.index) if extended_teardown_hooks: test_dict["teardown_hooks"] = extended_teardown_hooks # TODO: extend with other api definition items, e.g. times test_dict.update(api_def_dict)
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"] = [ 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
def test_extend_variables_fix(self): raw_variables = [{"var1": "val1"}, {"var2": "val2"}] override_variables = {} extended_variables_mapping = utils.extend_variables( raw_variables, override_variables) self.assertEqual(extended_variables_mapping["var1"], "val1")