def __extend_with_api_ref(raw_testinfo): """ extend with api reference Raises: exceptions.ApiNotFound: api not found """ api_name = raw_testinfo["api"] # api maybe defined in two types: # 1, individual file: each file is corresponding to one api definition # 2, api sets file: one file contains a list of api definitions if not os.path.isabs(api_name): # make compatible with Windows/Linux pwd = get_project_working_directory() api_path = os.path.join(pwd, *api_name.split("/")) if os.path.isfile(api_path): # type 1: api is defined in individual file api_name = api_path if api_name in tests_def_mapping["api"]: block = tests_def_mapping["api"][api_name] elif not os.path.isfile(api_name): raise exceptions.ApiNotFound("{} not found!".format(api_name)) else: block = load_file(api_name) # NOTICE: avoid project_mapping been changed during iteration. raw_testinfo["api_def"] = utils.deepcopy_dict(block) tests_def_mapping["api"][api_name] = block
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)
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
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
def test_deepcopy_dict(self): data = { 'a': 1, 'b': [2, 4], 'c': lambda x: x+1, 'd': open('LICENSE'), 'f': { 'f1': {'a1': 2}, 'f2': io.open('LICENSE', 'rb'), } } new_data = utils.deepcopy_dict(data) data["a"] = 0 self.assertEqual(new_data["a"], 1) data["f"]["f1"] = 123 self.assertEqual(new_data["f"]["f1"], {'a1': 2}) self.assertNotEqual(id(new_data["b"]), id(data["b"])) self.assertEqual(id(new_data["c"]), id(data["c"]))
def test_deepcopy_dict(self): license_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), "LICENSE") data = { 'a': 1, 'b': [2, 4], 'c': lambda x: x + 1, 'd': open(license_path), 'f': { 'f1': { 'a1': 2 }, 'f2': io.open(license_path, 'rb'), } } new_data = utils.deepcopy_dict(data) data["a"] = 0 self.assertEqual(new_data["a"], 1) data["f"]["f1"] = 123 self.assertEqual(new_data["f"]["f1"], {'a1': 2}) self.assertNotEqual(id(new_data["b"]), id(data["b"])) self.assertEqual(id(new_data["c"]), id(data["c"]))
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_user.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 overrided_testcase_config_variables = utils.extend_variables( parsed_testcase["config"].pop("variables", {}), testcase_config_variables) if overrided_testcase_config_variables: parsed_testcase["config"][ "variables"] = overrided_testcase_config_variables # parse config variables parsed_config_variables = parse_variables_mapping( overrided_testcase_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 testcase_copied = utils.deepcopy_dict(parsed_testcase) parsed_config_variables_copied = utils.deepcopy_dict( parsed_config_variables) testcase_copied["config"][ "variables"] = utils.extend_variables( parsed_config_variables_copied, parameter_variables) parsed_testcase_copied = _parse_testcase( testcase_copied, project_mapping) parsed_testcase_copied["config"]["name"] = parse_lazy_data( parsed_testcase_copied["config"]["name"], testcase_copied["config"]["variables"]) parsed_testcase_list.append(parsed_testcase_copied) else: parsed_testcase = _parse_testcase(parsed_testcase, project_mapping) parsed_testcase_list.append(parsed_testcase) return parsed_testcase_list
def parse_tests(testcases, variables_mapping=None): """ parse testcases configs, including variables/parameters/name/request. Args: testcases (list): testcase list, with config unparsed. [ { # testcase data structure "config": { "name": "desc1", "path": "testcase1_path", "variables": [], # optional "request": {} # optional "refs": { "debugtalk": { "variables": {}, "functions": {} }, "env": {}, "def-api": {}, "def-testcase": {} } }, "teststeps": [ # teststep data structure { 'name': 'test step desc2', 'variables': [], # optional 'extract': [], # optional 'validate': [], 'request': {}, 'function_meta': {} }, teststep2 # another teststep dict ] }, testcase_dict_2 # another testcase dict ] variables_mapping (dict): if variables_mapping is specified, it will override variables in config block. Returns: list: parsed testcases list, with config variables/parameters/name/request parsed. """ variables_mapping = variables_mapping or {} parsed_testcases_list = [] for testcase in testcases: testcase_config = testcase.setdefault("config", {}) project_mapping = testcase_config.pop( "refs", { "debugtalk": { "variables": {}, "functions": {} }, "env": {}, "def-api": {}, "def-testcase": {} } ) # parse config parameters config_parameters = testcase_config.pop("parameters", []) cartesian_product_parameters_list = parse_parameters( config_parameters, project_mapping["debugtalk"]["variables"], project_mapping["debugtalk"]["functions"] ) or [{}] for parameter_mapping in cartesian_product_parameters_list: testcase_dict = utils.deepcopy_dict(testcase) config = testcase_dict.get("config") # parse config variables raw_config_variables = config.get("variables", []) parsed_config_variables = parse_data( raw_config_variables, project_mapping["debugtalk"]["variables"], project_mapping["debugtalk"]["functions"] ) # priority: passed in > debugtalk.py > parameters > variables # override variables mapping with parameters mapping config_variables = utils.override_mapping_list( parsed_config_variables, parameter_mapping) # merge debugtalk.py module variables config_variables.update(project_mapping["debugtalk"]["variables"]) # override variables mapping with passed in variables_mapping config_variables = utils.override_mapping_list( config_variables, variables_mapping) testcase_dict["config"]["variables"] = config_variables # parse config name testcase_dict["config"]["name"] = parse_data( testcase_dict["config"].get("name", ""), config_variables, project_mapping["debugtalk"]["functions"] ) # parse config request testcase_dict["config"]["request"] = parse_data( testcase_dict["config"].get("request", {}), config_variables, project_mapping["debugtalk"]["functions"] ) # put loaded project functions to config testcase_dict["config"]["functions"] = project_mapping["debugtalk"]["functions"] parsed_testcases_list.append(testcase_dict) return parsed_testcases_list