def _get_block_by_name(ref_call, ref_type): """ get test content by reference name @params: ref_call: e.g. api_v1_Account_Login_POST($UserName, $Password) ref_type: "api" or "suite" """ function_meta = parser.parse_function(ref_call) func_name = function_meta["func_name"] call_args = function_meta["args"] block = _get_test_definition(func_name, ref_type) def_args = block.get("function_meta").get("args", []) if len(call_args) != len(def_args): raise exceptions.ParamsError("call args mismatch defined args!") args_mapping = {} for index, item in enumerate(def_args): if call_args[index] == item: continue args_mapping[item] = call_args[index] if args_mapping: block = utils.substitute_variables_with_mapping(block, args_mapping) return block
def load_api_folder(api_folder_path): """ load api definitions from api folder. Args: api_folder_path (str): api files folder. api file should be in the following format: [ { "api": { "def": "api_login", "request": {}, "validate": [] } }, { "api": { "def": "api_logout", "request": {}, "validate": [] } } ] Returns: dict: api definition mapping. { "api_login": { "function_meta": {"func_name": "api_login", "args": [], "kwargs": {}} "request": {} }, "api_logout": { "function_meta": {"func_name": "api_logout", "args": [], "kwargs": {}} "request": {} } } """ api_definition_mapping = {} api_items_mapping = load_folder_content(api_folder_path) for api_file_path, api_items in api_items_mapping.items(): # TODO: add JSON schema validation for api_item in api_items: key, api_dict = api_item.popitem() api_def = api_dict.pop("def") function_meta = parser.parse_function(api_def) func_name = function_meta["func_name"] if func_name in api_definition_mapping: logger.log_warning( "API definition duplicated: {}".format(func_name)) api_dict["function_meta"] = function_meta api_definition_mapping[func_name] = api_dict return api_definition_mapping
def _eval_content_functions(self, content): functions_list = parser.extract_functions(content) for func_content in functions_list: function_meta = parser.parse_function(func_content) func_name = function_meta['func_name'] args = function_meta.get('args', []) kwargs = function_meta.get('kwargs', {}) args = self.eval_content_with_bindings(args) kwargs = self.eval_content_with_bindings(kwargs) if func_name in ["parameterize", "P"]: eval_value = self.load_csv_list(*args, **kwargs) else: func = self.get_bind_function(func_name) eval_value = func(*args, **kwargs) func_content = "${" + func_content + "}" if func_content == content: # content is a variable content = eval_value else: # content contains one or many variables content = content.replace(func_content, str(eval_value), 1) return content
def run_hook(request_or_response=None, hooks=None): # 运行setup_hooks or teardown_hooks # hooks = [${func1($request, 1,2)}, ${func2(key=value)}] function_regexp = re.compile(r"\$\{([\w_]+\([\$\w\.\-/_ =,]*\))\}") return_value_list = [] if hooks: utils_functions_mapping = utils.get_functions_mapping() functions_string_list = re.findall(function_regexp, hooks) for function_string in functions_string_list: # e.g. function_string = 'func1(1,2)' # e.g. function_parse_dict = {'func_name': 'func1', 'args': [1, 2], 'kwargs': {}} function_parse_dict = parser.parse_function(function_string) try: function_name = function_parse_dict['func_name'] args = function_parse_dict['args'] # args: (1,2) for index, arg in enumerate(args): if arg in ['$response', '$request']: args[index] = request_or_response kwargs = function_parse_dict['kwargs'] # kwargs: {'a': 1} return_value = utils_functions_mapping[function_name](*args, **kwargs) logger.info('执行回调函数: {},获得返回值: {}'.format( function_parse_dict, return_value)) return_value_list.append(return_value) except Exception as e: logger.error( '执行回调函数报错:', 'function_parse_dict : {}'.format(function_parse_dict)) logger.error(e) return return_value_list
def test_parse_function(self): self.assertEqual( parser.parse_function("func()"), {'func_name': 'func', 'args': [], 'kwargs': {}} ) self.assertEqual( parser.parse_function("func(5)"), {'func_name': 'func', 'args': [5], 'kwargs': {}} ) self.assertEqual( parser.parse_function("func(1, 2)"), {'func_name': 'func', 'args': [1, 2], 'kwargs': {}} ) self.assertEqual( parser.parse_function("func(a=1, b=2)"), {'func_name': 'func', 'args': [], 'kwargs': {'a': 1, 'b': 2}} ) self.assertEqual( parser.parse_function("func(a= 1, b =2)"), {'func_name': 'func', 'args': [], 'kwargs': {'a': 1, 'b': 2}} ) self.assertEqual( parser.parse_function("func(1, 2, a=3, b=4)"), {'func_name': 'func', 'args': [1, 2], 'kwargs': {'a': 3, 'b': 4}} ) self.assertEqual( parser.parse_function("func($request, 123)"), {'func_name': 'func', 'args': ["$request", 123], 'kwargs': {}} ) self.assertEqual( parser.parse_function("func( )"), {'func_name': 'func', 'args': [], 'kwargs': {}} ) self.assertEqual( parser.parse_function("func(hello world, a=3, b=4)"), {'func_name': 'func', 'args': ["hello world"], 'kwargs': {'a': 3, 'b': 4}} ) self.assertEqual( parser.parse_function("func($request, 12 3)"), {'func_name': 'func', 'args': ["$request", '12 3'], 'kwargs': {}} )
def load_api_folder(api_folder_path): ''' load api definitions from api folder. Args: api_folder_path (str): api files folder. { 'api':{ 'def':'api_login', 'request':{}, 'validate':[] } }, { 'api':{ 'def':'api_logout', 'request':{}, 'validate':[] } } Returns: dict: api definition mapping. { 'api_login':{ 'function_mata':{'func_name':'api_login','args':[],'kwargs':{}}, 'request':{} }, 'api_logout':{ 'function_mata':{'func_name':'api_logout','args':[],'kwargs':{}}, 'request':{} } } ''' api_definition_mapping = {} api_items_mapping = load_folder_content(api_folder_path) for api_file_path, api_items in api_items_mapping.items(): for api_item in api_items: key, api_dict = api_item.popitem() api_def = api_dict.pop('def') function_meta = parser.parse_function(api_def) func_name = function_meta['func_name'] if func_name in api_definition_mapping: logger.log_warning(f'API definition duplicated: {func_name}') api_dict['function_meta'] = function_meta api_definition_mapping[func_name] = api_dict project_mapping['def-api'] = api_definition_mapping return api_definition_mapping
def _load_api_file(file_path): """ load api definition from file and store in overall_def_dict["api"] api file should be in format below: [ { "api": { "def": "api_login", "request": {}, "validate": [] } }, { "api": { "def": "api_logout", "request": {}, "validate": [] } } ] """ api_items = load_file(file_path) if not isinstance(api_items, list): raise exceptions.FileFormatError( "API format error: {}".format(file_path)) for api_item in api_items: if not isinstance(api_item, dict) or len(api_item) != 1: raise exceptions.FileFormatError( "API format error: {}".format(file_path)) key, api_dict = api_item.popitem() if key != "api" or not isinstance(api_dict, dict) or "def" not in api_dict: raise exceptions.FileFormatError( "API format error: {}".format(file_path)) api_def = api_dict.pop("def") function_meta = parser.parse_function(api_def) func_name = function_meta["func_name"] if func_name in overall_def_dict["api"]: logger.log_warning( "API definition duplicated: {}".format(func_name)) api_dict["function_meta"] = function_meta overall_def_dict["api"][func_name] = api_dict
def _get_block_by_name(ref_call, ref_type, project_mapping): """ get test content by reference name. Args: ref_call (str): call function. e.g. api_v1_Account_Login_POST($UserName, $Password) ref_type (enum): "def-api" or "def-testcase" project_mapping (dict): project_mapping Returns: dict: api/testcase definition. Raises: exceptions.ParamsError: call args number is not equal to defined args number. """ function_meta = parser.parse_function(ref_call) func_name = function_meta["func_name"] call_args = function_meta["args"] block = _get_test_definition(func_name, ref_type, project_mapping) def_args = block.get("function_meta", {}).get("args", []) if len(call_args) != len(def_args): err_msg = "{}: call args number is not equal to defined args number!\n".format( func_name) err_msg += "defined args: {}\n".format(def_args) err_msg += "reference args: {}".format(call_args) logger.log_error(err_msg) raise exceptions.ParamsError(err_msg) args_mapping = {} for index, item in enumerate(def_args): if call_args[index] == item: continue args_mapping[item] = call_args[index] if args_mapping: block = parser.substitute_variables(block, args_mapping) return block
def load_test_dependencies(): """ load all api and suite definitions. default api folder is "$CWD/tests/api/". default suite folder is "$CWD/tests/suite/". """ # TODO: cache api and suite loading # load api definitions api_def_folder = os.path.join(os.getcwd(), "tests", "api") for test_file in load_folder_files(api_def_folder): load_api_file(test_file) # load suite definitions suite_def_folder = os.path.join(os.getcwd(), "tests", "suite") for suite_file in load_folder_files(suite_def_folder): suite = load_test_file(suite_file) if "def" not in suite["config"]: raise exceptions.ParamsError("def missed in suite file: {}!".format(suite_file)) call_func = suite["config"]["def"] function_meta = parser.parse_function(call_func) suite["function_meta"] = function_meta overall_def_dict["suite"][function_meta["func_name"]] = suite
def _get_block_by_name(ref_call, ref_type): ''' get test content by reference name. Args: ref_call (str): call function. e.g. api_v1_Account_Login_POST($UserName,$Password) ref_type (enum): "def-api" or "def-testcase" Returns: dict: api/testcase definition Raises: exceptions.ParamsError: call args number is not equal to defined args number ''' function_meta = parser.parse_function(ref_call) func_name = function_meta['func_name'] call_args = function_meta['args'] block = _get_test_definition(func_name, ref_type) def_args = block.get('function_meta', {}).get('args', []) if len(call_args) != len(def_args): err_msg = f'{func_name}: call args number is not equal to defined args number!\n' err_msg += f'defined args: {def_args}\n' err_msg += f'refererce args: {call_args}' logger.log_error(err_msg) raise exceptions.ParamError(err_msg) args_mapping = {} for index, item in enumerate(def_args): if call_args[index] == item: continue args_mapping[item] = call_args[index] if args_mapping: block = parser.substitute_variables(block, args_mapping) return block
def load_test_folder(test_folder_path): """ load testcases definitions from folder. Args: test_folder_path (str): testcases files folder. testcase file should be in the following format: [ { "config": { "def": "create_and_check", "request": {}, "validate": [] } }, { "test": { "api": "get_user", "validate": [] } } ] Returns: dict: testcases definition mapping. { "create_and_check": [ {"config": {}}, {"test": {}}, {"test": {}} ], "tests/testcases/create_and_get.yml": [ {"config": {}}, {"test": {}}, {"test": {}} ] } """ test_definition_mapping = {} test_items_mapping = load_folder_content(test_folder_path) for test_file_path, items in test_items_mapping.items(): # TODO: add JSON schema validation testcase = {"config": {}, "teststeps": []} for item in items: key, block = item.popitem() if key == "config": testcase["config"].update(block) if "def" not in block: test_definition_mapping[test_file_path] = testcase continue testcase_def = block.pop("def") function_meta = parser.parse_function(testcase_def) func_name = function_meta["func_name"] if func_name in test_definition_mapping: logger.log_warning( "API definition duplicated: {}".format(func_name)) testcase["function_meta"] = function_meta test_definition_mapping[func_name] = testcase else: # key == "test": testcase["teststeps"].append(block) project_mapping["def-testcase"] = test_definition_mapping return test_definition_mapping
def test_parse_function(self): assert parser.parse_function('func()') == { 'func_name': 'func', 'args': [], 'kwargs': {} } assert parser.parse_function('func(5)') == { 'func_name': 'func', 'args': [5], 'kwargs': {} } assert parser.parse_function('func(1, 2)') == { 'func_name': 'func', 'args': [1, 2], 'kwargs': {} } assert parser.parse_function('func(a=1, b=2)') == { 'func_name': 'func', 'args': [], 'kwargs': { 'a': 1, 'b': 2 } } assert parser.parse_function('func(a = 1, b = 2 )') == { 'func_name': 'func', 'args': [], 'kwargs': { 'a': 1, 'b': 2 } } assert parser.parse_function('func(1, 2, a=3, b=4)') == { 'func_name': 'func', 'args': [1, 2], 'kwargs': { 'a': 3, 'b': 4 } } assert parser.parse_function('func($request,123)') == { 'func_name': 'func', 'args': ['$request', 123], 'kwargs': {} } assert parser.parse_function('func( )') == { 'func_name': 'func', 'args': [], 'kwargs': {} } assert parser.parse_function('func(hello world, a=3, b=4)') == { 'func_name': 'func', 'args': ["hello world"], 'kwargs': { 'a': 3, 'b': 4 } } assert parser.parse_function('func($request, 12 3)') == { 'func_name': 'func', 'args': ["$request", "12 3"], 'kwargs': {} }
def load_test_folder(test_folder_path): ''' load testcases definition from folder. Args: test_folder_path (str): testcases files folder. testcase file should in the following format: [ { "config":{ "def":"create_and_check", "request":{}, "validate":[] } }, { "test":{ "api":"get_user", "validate":[] } } ] Returns: dict: testcases definition mapping. { "create_and_check":[ {"config":{}}, {"test":{}}, {"test":{}} ], "tests/testcases/create_and_get.yml":[ {"config":{}}, {"test":{}}, {"test":{}} ] } ''' test_definition_mapping = {} test_items_mapping = load_folder_content(test_folder_path) for test_file_path, items in test_items_mapping.items(): testcase = {"config": {}, "teststeps": []} for item in items: key, block = item.popitem() if key == 'config': testcase['config'].update(block) if "def" not in block: test_definition_mapping[test_file_path] = testcase continue testcase_def = block['def'] function_meta = parser.parse_function(testcase_def) func_name = function_meta['func_name'] if func_name in test_definition_mapping: logger.log_warning( f'testcase definition duplicated: {func_name}') testcase['function_meta'] = function_meta test_definition_mapping[func_name] = testcase else: testcase['teststeps'].append(block) project_mapping['def-testcase'] = test_definition_mapping return test_definition_mapping
def test_parse_function(self): assert parser.parse_function("func()") == { 'func_name': 'func', 'args': [], 'kwargs': {} } assert parser.parse_function("func(5)") == { 'func_name': 'func', 'args': [5], 'kwargs': {} } assert parser.parse_function("func(1, 2)") == { 'func_name': 'func', 'args': [1, 2], 'kwargs': {} } assert parser.parse_function("func(a=1,b=2)") == { 'func_name': 'func', 'args': [], 'kwargs': { 'a': 1, 'b': 2 } } assert parser.parse_function("func(a=1, b =2)") == { 'func_name': 'func', 'args': [], 'kwargs': { 'a': 1, 'b': 2 } } assert parser.parse_function("func(1, 2, a=3, b=4)") == { 'func_name': 'func', 'args': [1, 2], 'kwargs': { 'a': 3, 'b': 4 } } assert parser.parse_function("func($request,123)") == { 'func_name': 'func', 'args': ['$request', 123], 'kwargs': {} } assert parser.parse_function("func( )") == { 'func_name': 'func', 'args': [], 'kwargs': {} } assert parser.parse_function("func(hello world, a=3, b=4)") == { 'func_name': 'func', 'args': ['hello world'], 'kwargs': { 'a': 3, 'b': 4 } } assert parser.parse_function("func($request, 12.3)") == { 'func_name': 'func', 'args': ['$request', 12.3], 'kwargs': {} }