def create_command_results_assertion(arg: str, value: Union[ast_mod.Name, ast_mod.Constant]): """ Inputs: arg: CommandResults argument value: CommandResults argument value Returns: Single assertion as part of command results assertions """ comperator = None call = ast_mod.Attribute(value=ast_name('results'), attr=arg) ops = [ast_mod.Eq()] if hasattr(value, 'value'): # if so it is of type ast.Constant comperator = ast_mod.Constant(value=value.value) elif arg == 'raw_response': link = TestCase.get_links(value) if link: comperator = ast_name(f'mock_response_{link}') elif arg == 'outputs' or arg == 'readable_output': get_call = ast_mod.Call(func=ast_name('get'), args=[ast_mod.Constant(arg)], keywords=[]) comperator = ast_mod.Attribute(value=ast_name('mock_results'), attr=get_call, ctx=ast_mod.Load()) return TestCase.assertions_builder( call, ops, [comperator]) if comperator else None
def to_ast(self): """ Converting test_case object to ast. """ body = [ast_mod.Expr(value=ast_mod.Constant(value=self.comment))] body.extend(self.inputs) body.extend(self.mocks) body.append(self.command_call) body.extend(self.asserts) request_mocker = ast_name('requests_mock') args = [self.client_name, request_mocker] if self.global_arg: args.append(ast_name('args')) test_func = ast_mod.FunctionDef(name=f"test_{self.func.name}", args=ast_mod.arguments(posonlyargs=[], args=args, vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=body, decorator_list=self.decorators, returns=None) return test_func
def build_decorator(self): """ builds decorator of parametrize. """ call = ast_mod.Call( func=ast_name('pytest.mark.parametrize'), args=[ast_mod.Constant('args'), ast_name(self.global_arg_name)], keywords=[]) self.decorators.append(call)
def load_mock_from_json_ast_builder(self, name: str, call: str): """ Args: name: name of the object to store the json. call: name of the call, used to decide which file to choose from outputs directory. Return: Assign ast node of assignment of the mocked object. """ return ast_mod.Assign( targets=[ast_name(name, ctx=ast_mod.Store())], value=ast_mod.Call( func=ast_name('util_load_json'), args=[ ast_mod.Constant( value='./' + str(Path('test_data', 'outputs', f'{call}.json'))) ], keywords=[]))
def generate_test_client(self): """ Return: client function to mock """ client_init_args = self.get_client_init_args(self.get_client_ast()) keywords = [] for arg in client_init_args: arg_name = arg.arg arg_annotation = str(arg.annotation) if hasattr( arg, 'annotation') else None if 'url' in arg_name: keywords.append( ast_mod.keyword(arg=arg_name, value=ast_name('SERVER_URL'))) elif arg_annotation and arg_annotation == 'bool': keywords.append( ast_mod.keyword(arg=arg_name, value=ast_name('True'))) elif arg_annotation and arg_annotation == 'str': keywords.append( ast_mod.keyword(arg=arg_name, value=ast_mod.Constant('test'))) elif arg_name != 'self': keywords.append( ast_mod.keyword(arg=arg_name, value=ast_name('None'))) body = [ ast_mod.Return(value=ast_mod.Call( func=ast_name('Client'), args=[], keywords=keywords)) ] func = ast_mod.FunctionDef(name="client", args=ast_mod.arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=body, decorator_list=[ ast_mod.Call(func=ast_mod.Attribute( value=ast_name('pytest'), attr='fixture'), args=[], keywords=[]) ], returns=None) return func
def build_local_args(self): """ build a local var named args that will be given as input to the command. """ keys, values = self.get_keys_values(self.input_args[0]) self.args.append( ast_mod.Assign(targets=[ast_name('args', ctx=ast_mod.Store())], value=ast_mod.Dict(keys=keys, values=values)))
def call_command_ast_builder(self): """ Input: command_name: name of the command being called Returns: ast node of assignment command results to var. """ call_keywords = [ ast_mod.keyword(arg='client', value=ast_name('client')) ] if len(self.args_list) > 0: call_keywords.append( ast_mod.keyword(arg='args', value=ast_name('args'))) self.command_call = ast_mod.Assign( targets=[ast_name('results', ctx=ast_mod.Store())], value=ast_mod.Call(func=ast_name(self.func.name), args=[], keywords=call_keywords))
def util_json_builder(self): """ Return: ast sub-tree of a function to read and parse json file: with io.open(path, mode='r', encoding='utf-8') as f: return json.loads(f.read()) """ io_open = ast_mod.Call( func=ast_mod.Attribute(value=ast_name('io'), attr=ast_name('open')), args=[ast_name('path')], keywords=[ ast_mod.keyword(arg='mode', value=ast_mod.Constant(value='r')), ast_mod.keyword(arg='encoding', value=ast_mod.Constant(value='utf-8')) ]) f_read = ast_mod.Call(ast_mod.Attribute(value=ast_name('f'), attr=ast_name('read')), args=[], keywords=[]) return_node = ast_mod.Return(value=ast_mod.Call(func=ast_mod.Attribute( value=ast_name('json'), attr=ast_name('loads')), args=[f_read], keywords=[])) body = [ ast_mod.With(items=[ ast_mod.withitem(context_expr=io_open, optional_vars=ast_name('f')) ], body=[ast_mod.Expr(value=return_node)]) ] func = ast_mod.FunctionDef(name="util_load_json", args=ast_mod.arguments( posonlyargs=[], args=[ast_name('path')], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=body, decorator_list=[], returns=None) return func
def build_global_args(self): """ builds a global var named after the command name, it will hold all arguments given. """ self.global_arg_name = f'{self.command_name.upper()}_ARGS' global_args = [] for inputs in self.input_args: keys, values = self.get_keys_values(inputs) global_args.append(ast_mod.Dict(keys=keys, values=values)) self.global_arg.append( ast_mod.Assign( targets=[ast_name(self.global_arg_name, ast_mod.Store())], value=ast_mod.List(elts=global_args, ctx=ast_mod.Store())))
def request_mock_ast_builder(self): """ Builds ast nodes of requests mock. """ for call in self.client_func_call: self.mocks.append( self.load_mock_from_json_ast_builder(f'mock_response_{call}', call)) self.mocks.append( self.load_mock_from_json_ast_builder('mock_results', str(self.func.name))) suffix, method = self.get_call_params_from_http_request(call) url = f'SERVER_URL + \'{suffix}\'' if suffix is not None else 'SERVER_URL' attr = ast_mod.Attribute(value=ast_name('requests_mock'), attr=ast_name(method.lower())) ret_val = ast_mod.keyword(arg=ast_name('json'), value=ast_name(f'mock_response_{call}')) mock_call = ast_mod.Call(func=attr, args=[ast_name(url)], keywords=[ret_val]) self.mocks.append(ast_mod.Expr(value=mock_call))
def __init__(self, tree: ast_mod.Module, module_name: str, to_concat: bool, module: ast_mod.Module = None): self.functions = [] self.imports = [ ast_mod.Import(names=[ast_mod.alias(name='pytest', asname=None)]), ast_mod.Import(names=[ast_mod.alias(name='io', asname=None)]), ast_mod.ImportFrom(module='CommonServerPython', names=[ast_mod.alias(name='*', asname=None)], level=0) ] self.module = module self.server_url = ast_mod.Assign( targets=[ast_name('SERVER_URL')], value=ast_mod.Constant(value='https://test_url.com')) self.tree = tree self.module_name = module_name self.global_args = [] self.to_concat = to_concat
def build_imports(self, names_to_import: list): aliases = [ast_name(name) for name in names_to_import] return ast_mod.ImportFrom(module=self.module_name, names=aliases, level=0)