def build_url(base_url: Text, path: Text): """ prepend url with base_url unless it's already an absolute URL """ if absolute_http_url_regexp.match(path): return path elif base_url: return "{}/{}".format(base_url.rstrip("/"), path.lstrip("/")) else: raise exceptions.ParamsError("base url missed!")
def __run_step_testcase(self, step: TStep) -> StepData: """run teststep: referenced testcase""" step_data = StepData(name=step.name) step_variables = step.variables step_export = step.export # setup hooks if step.setup_hooks: self.__call_hooks(step.setup_hooks, step_variables, "setup testcase") if hasattr(step.testcase, "config") and hasattr( step.testcase, "teststeps"): testcase_cls = step.testcase case_result = (testcase_cls().with_session( self.__session).with_case_id(self.__case_id).with_variables( step_variables).with_export(step_export).run()) elif isinstance(step.testcase, Text): if os.path.isabs(step.testcase): ref_testcase_path = step.testcase else: ref_testcase_path = os.path.join(self.__project_meta.RootDir, step.testcase) case_result = (HttpRunner().with_session( self.__session).with_case_id( self.__case_id).with_variables(step_variables).with_export( step_export).run_path(ref_testcase_path)) else: raise exceptions.ParamsError( f"Invalid teststep referenced testcase: {step.dict()}") # teardown hooks if step.teardown_hooks: self.__call_hooks(step.teardown_hooks, step.variables, "teardown testcase") step_data.data = case_result.get_step_datas() # list of step data step_data.export_vars = case_result.get_export_variables() step_data.success = case_result.success self.success = case_result.success if step_data.export_vars: logger.info(f"export variables: {step_data.export_vars}") return step_data
def __getattr__(self, key): if key in ["json", "content", "body"]: try: value = self.resp_obj.json() except ValueError: value = self.resp_obj.content elif key == "cookies": value = self.resp_obj.cookies.get_dict() else: try: value = getattr(self.resp_obj, key) except AttributeError: err_msg = "ResponseObject does not have attribute: {}".format(key) logger.error(err_msg) raise exceptions.ParamsError(err_msg) self.__dict__[key] = value return value
def convert_relative_project_root_dir(abs_path: Text) -> Text: """ convert absolute path to relative path, based on project_meta.RootDir Args: abs_path: absolute path Returns: relative path based on project_meta.RootDir """ _project_meta = load_project_meta(abs_path) if not abs_path.startswith(_project_meta.RootDir): raise exceptions.ParamsError( f"failed to convert absolute path to relative path based on project_meta.RootDir\n" f"abs_path: {abs_path}\n" f"project_meta.RootDir: {_project_meta.RootDir}" ) return abs_path[len(_project_meta.RootDir) + 1 :]
def parse_parameters(parameters: Dict, ) -> List[Dict]: """ parse parameters and generate cartesian product. Args: parameters (Dict) parameters: parameter name and value mapping 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()}" 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) """ parsed_parameters_list: List[List[Dict]] = [] # load project_meta functions project_meta = loader.load_project_meta(os.getcwd()) functions_mapping = project_meta.functions 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: List[Dict] = [] 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) elif isinstance(parameter_content, Text): # (2) & (3) parsed_parameter_content: List = parse_data( parameter_content, {}, functions_mapping ) if not isinstance(parsed_parameter_content, List): raise exceptions.ParamsError( f"parameters content should be in List type, got {parsed_parameter_content} for {parameter_content}" ) parameter_content_list: List[Dict] = [] 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: Dict = { key: parameter_item[key] for key in parameter_name_list } elif isinstance(parameter_item, (List, tuple)): if len(parameter_name_list) == len(parameter_item): # {"username-password": "******"} # get_account() => [("user1", "111111"), ("user2", "222222")] parameter_dict = dict(zip(parameter_name_list, parameter_item)) else: raise exceptions.ParamsError( f"parameter names length are not equal to value length.\n" f"parameter names: {parameter_name_list}\n" f"parameter values: {parameter_item}" ) elif len(parameter_name_list) == 1: # {"user_agent": "${get_user_agent()}"} # get_user_agent() => ["iOS/10.1", "iOS/10.2"] # parameter_dict will get: {"user_agent": "iOS/10.1", "user_agent": "iOS/10.2"} parameter_dict = {parameter_name_list[0]: parameter_item} else: raise exceptions.ParamsError( f"Invalid parameter names and values:\n" f"parameter names: {parameter_name_list}\n" f"parameter values: {parameter_item}" ) parameter_content_list.append(parameter_dict) else: raise exceptions.ParamsError( f"parameter content should be List or Text(variables or functions call), got {parameter_content}" ) parsed_parameters_list.append(parameter_content_list) return utils.gen_cartesian_product(*parsed_parameters_list)
def run_path(self, path: Text) -> "HttpRunner": if not os.path.isfile(path): raise exceptions.ParamsError(f"Invalid testcase path: {path}") testcase_obj = load_testcase_file(path) return self.run_testcase(testcase_obj)