def run_step_testcase(runner: HttpRunner, step: TStep) -> StepResult: """run teststep: referenced testcase""" step_result = StepResult(name=step.name) step_variables = step.variables step_export = step.export # setup hooks if step.setup_hooks: call_hooks(runner, step.setup_hooks, step_variables, "setup testcase") # TODO: override testcase with current step name/variables/export # step.testcase is a referenced testcase, e.g. RequestWithFunctions ref_case_runner = step.testcase() ref_case_runner.with_session(runner.session).with_case_id( runner.case_id).with_variables(step_variables).with_export( step_export).test_start() # teardown hooks if step.teardown_hooks: call_hooks(runner, step.teardown_hooks, step.variables, "teardown testcase") summary: TestCaseSummary = ref_case_runner.get_summary() step_result.data = summary.step_results # list of step data step_result.export_vars = summary.in_out.export_vars step_result.success = summary.success if step_result.export_vars: logger.info(f"export variables: {step_result.export_vars}") return step_result
def prepare_upload_step(step: TStep, functions: FunctionsMapping): """preprocess for upload test replace `upload` info with MultipartEncoder Args: step: teststep { "variables": {}, "request": { "url": "http://httpbin.org/upload", "method": "POST", "headers": { "Cookie": "session=AAA-BBB-CCC" }, "upload": { "file": "data/file_to_upload" "md5": "123" } } } functions: functions mapping """ if not step.request.upload: return # parse upload info step.request.upload = parse_data(step.request.upload, step.variables, functions) ensure_upload_ready() params_list = [] for key, value in step.request.upload.items(): step.variables[key] = value params_list.append(f"{key}=${key}") params_str = ", ".join(params_list) step.variables["m_encoder"] = "${multipart_encoder(" + params_str + ")}" # parse variables step.variables = parse_variables_mapping(step.variables, functions) step.request.headers["Content-Type"] = "${multipart_content_type($m_encoder)}" step.request.data = "$m_encoder"
def __run_step_request(self, step: TStep) -> StepData: """run teststep: request""" step_data = StepData(name=step.name) # parse prepare_upload_step(step, self.__project_meta.functions) request_dict = step.request.dict() request_dict.pop("upload", None) parsed_request_dict = parse_data(request_dict, step.variables, self.__project_meta.functions) parsed_request_dict["headers"].setdefault( "HRUN-Request-ID", f"HRUN-{self.__case_id}-{str(int(time.time() * 1000))[-6:]}", ) step.variables["request"] = parsed_request_dict # setup hooks if step.setup_hooks: self.__call_hooks(step.setup_hooks, step.variables, "setup") # prepare arguments method = parsed_request_dict.pop("method") url_path = parsed_request_dict.pop("url") url = build_url(self.__config.base_url, url_path) parsed_request_dict["verify"] = self.__config.verify parsed_request_dict["json"] = parsed_request_dict.pop("req_json", {}) # request resp = self.__session.request(method, url, **parsed_request_dict) resp_obj = ResponseObject(resp) step.variables["response"] = resp_obj # teardown hooks if step.teardown_hooks: self.__call_hooks(step.teardown_hooks, step.variables, "teardown") def log_req_resp_details(): err_msg = "\n{} DETAILED REQUEST & RESPONSE {}\n".format( "*" * 32, "*" * 32) # log request err_msg += "====== request details ======\n" err_msg += f"url: {url}\n" err_msg += f"method: {method}\n" headers = parsed_request_dict.pop("headers", {}) err_msg += f"headers: {headers}\n" for k, v in parsed_request_dict.items(): v = utils.omit_long_data(v) err_msg += f"{k}: {repr(v)}\n" err_msg += "\n" # log response err_msg += "====== response details ======\n" err_msg += f"status_code: {resp.status_code}\n" err_msg += f"headers: {resp.headers}\n" err_msg += f"body: {repr(resp.text)}\n" logger.error(err_msg) # extract extractors = step.extract extract_mapping = resp_obj.extract(extractors) step_data.export_vars = extract_mapping variables_mapping = step.variables variables_mapping.update(extract_mapping) # validate validators = step.validators try: resp_obj.validate(validators, variables_mapping, self.__project_meta.functions) self.__session.data.success = True except ValidationFailure: self.__session.data.success = False log_req_resp_details() # log testcase duration before raise ValidationFailure self.__duration = time.time() - self.__start_at raise finally: # save request & response meta data self.__session.data.validators = resp_obj.validation_results self.success = self.__session.data.success # save step data step_data.success = self.__session.data.success step_data.data = self.__session.data return step_data
def __init__(self, name: Text): self.__step_context = TStep(name=name)
def run_step_request(runner: HttpRunner, step: TStep) -> StepResult: """run teststep: request""" step_result = StepResult( name=step.name, success=False, ) start_time = time.time() step.variables = runner.merge_step_variables(step.variables) # parse functions = runner.parser.functions_mapping prepare_upload_step(step, functions) request_dict = step.request.dict() request_dict.pop("upload", None) parsed_request_dict = runner.parser.parse_data(request_dict, step.variables) parsed_request_dict["headers"].setdefault( "HRUN-Request-ID", f"HRUN-{runner.case_id}-{str(int(time.time() * 1000))[-6:]}", ) step.variables["request"] = parsed_request_dict # setup hooks if step.setup_hooks: call_hooks(runner, step.setup_hooks, step.variables, "setup request") # prepare arguments config = runner.get_config() method = parsed_request_dict.pop("method") url_path = parsed_request_dict.pop("url") url = build_url(config.base_url, url_path) parsed_request_dict["verify"] = config.verify parsed_request_dict["json"] = parsed_request_dict.pop("req_json", {}) # request resp = runner.session.request(method, url, **parsed_request_dict) resp_obj = ResponseObject(resp, runner.parser) step.variables["response"] = resp_obj # teardown hooks if step.teardown_hooks: call_hooks(runner, step.teardown_hooks, step.variables, "teardown request") def log_req_resp_details(): err_msg = "\n{} DETAILED REQUEST & RESPONSE {}\n".format( "*" * 32, "*" * 32) # log request err_msg += "====== request details ======\n" err_msg += f"url: {url}\n" err_msg += f"method: {method}\n" headers = parsed_request_dict.pop("headers", {}) err_msg += f"headers: {headers}\n" for k, v in parsed_request_dict.items(): v = utils.omit_long_data(v) err_msg += f"{k}: {repr(v)}\n" err_msg += "\n" # log response err_msg += "====== response details ======\n" err_msg += f"status_code: {resp.status_code}\n" err_msg += f"headers: {resp.headers}\n" err_msg += f"body: {repr(resp.text)}\n" logger.error(err_msg) # extract extractors = step.extract extract_mapping = resp_obj.extract(extractors, step.variables) step_result.export_vars = extract_mapping variables_mapping = step.variables variables_mapping.update(extract_mapping) # validate validators = step.validators try: resp_obj.validate(validators, variables_mapping) step_result.success = True except ValidationFailure: log_req_resp_details() raise finally: session_data = runner.session.data session_data.success = step_result.success session_data.validators = resp_obj.validation_results # save step data step_result.data = session_data step_result.elapsed = time.time() - start_time return step_result