def setUp(self) -> None: resp = requests.post( "https://httpbin.org/anything", json={ "locations": [ { "name": "Seattle", "state": "WA" }, { "name": "New York", "state": "NY" }, { "name": "Bellevue", "state": "WA" }, { "name": "Olympia", "state": "WA" }, ] }, ) parser = Parser(functions_mapping={ "get_name": lambda: "name", "get_num": lambda x: x }) self.resp_obj = ResponseObject(resp, parser)
def setUp(self) -> None: resp = requests.post( "https://httpbin.org/anything", json={ "locations": [ { "name": "Seattle", "state": "WA" }, { "name": "New York", "state": "NY" }, { "name": "Bellevue", "state": "WA" }, { "name": "Olympia", "state": "WA" }, ] }, ) self.resp_obj = ResponseObject(resp)
def match_event_with_reports( response: ResponseObject, platform: PlatformEnum, event: Event, happen_after_seconds: int ) -> None: """ Match event with report records in database, matched records will be appended to response. When an event happens, corresponding report will be sent. """ # 1. filter filter_result: List[ReportLog] = crud.report_log.filter(db, event, platform, happen_after_seconds) filter_result_ids = [_.id for _ in filter_result] response.body["filter"] = filter_result_ids # 2. match matched_report_logs = match(filter_result, event) for report_log in matched_report_logs: update_data = {"matched": True} crud.report_log.update(db, db_obj=report_log, obj_in=update_data) matched_report_log_ids = [_.id for _ in matched_report_logs] response.body["match"] = matched_report_log_ids
def __run_step_request(self, step: TStep): """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) # 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["json"] = parsed_request_dict.pop("req_json", {}) logger.info(f"{method} {url}") logger.debug(f"request kwargs(raw): {parsed_request_dict}") # request self.__session = self.__session or HttpSession() resp = self.__session.request(method, url, **parsed_request_dict) resp_obj = ResponseObject(resp) 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 = 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() 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 __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
class TestResponse(unittest.TestCase): def setUp(self) -> None: resp = requests.post( "https://httpbin.org/anything", json={ "locations": [ { "name": "Seattle", "state": "WA" }, { "name": "New York", "state": "NY" }, { "name": "Bellevue", "state": "WA" }, { "name": "Olympia", "state": "WA" }, ] }, ) self.resp_obj = ResponseObject(resp) def test_extract(self): extract_mapping = self.resp_obj.extract({ "var_1": "body.json.locations[0]", "var_2": "body.json.locations[3].name" }) self.assertEqual(extract_mapping["var_1"], { "name": "Seattle", "state": "WA" }) self.assertEqual(extract_mapping["var_2"], "Olympia") def test_validate(self): variables_mapping = {"index": 1} self.resp_obj.validate( [ { "eq": ["body.json.locations[0].name", "Seattle"] }, { "eq": [ "body.json.locations[0]", { "name": "Seattle", "state": "WA" } ] }, { "eq": ["body.json.locations[$index].name", "New York"] }, ], variables_mapping=variables_mapping, )
class TestResponse(unittest.TestCase): def setUp(self) -> None: resp = requests.post( "https://httpbin.org/anything", json={ "locations": [ { "name": "Seattle", "state": "WA" }, { "name": "New York", "state": "NY" }, { "name": "Bellevue", "state": "WA" }, { "name": "Olympia", "state": "WA" }, ] }, ) parser = Parser(functions_mapping={ "get_name": lambda: "name", "get_num": lambda x: x }) self.resp_obj = ResponseObject(resp, parser) def test_extract(self): variables_mapping = {"body": "body"} extract_mapping = self.resp_obj.extract( { "var_1": "body.json.locations[0]", "var_2": "body.json.locations[3].name", "var_3": "$body.json.locations[3].name", "var_4": "$body.json.locations[3].${get_name()}", }, variables_mapping=variables_mapping, ) self.assertEqual(extract_mapping["var_1"], { "name": "Seattle", "state": "WA" }) self.assertEqual(extract_mapping["var_2"], "Olympia") self.assertEqual(extract_mapping["var_3"], "Olympia") self.assertEqual(extract_mapping["var_4"], "Olympia") def test_validate(self): self.resp_obj.validate([ { "eq": ["body.json.locations[0].name", "Seattle"] }, { "eq": ["body.json.locations[0]", { "name": "Seattle", "state": "WA" }] }, ], ) def test_validate_variables(self): variables_mapping = {"index": 1, "var_empty": ""} self.resp_obj.validate( [ { "eq": ["body.json.locations[$index].name", "New York"] }, { "eq": ["$var_empty", ""] }, ], variables_mapping=variables_mapping, ) def test_validate_functions(self): variables_mapping = {"index": 1} self.resp_obj.validate( [ { "eq": ["${get_num(0)}", 0] }, { "eq": ["${get_num($index)}", 1] }, ], variables_mapping=variables_mapping, )
def run_testcase(self, testcase: TestCase) -> "HttpRunner": """run specified testcase Examples: >>> testcase_obj = TestCase(config=TConfig(...), teststeps=[TStep(...)]) >>> HttpRunner().with_project_meta(project_meta).run_testcase(testcase_obj) """ self.__config = testcase.config self.__teststeps = testcase.teststeps # prepare self.__project_meta = self.__project_meta or load_project_meta( self.__config.path) self.__parse_config(self.__config) self.__start_at = time.time() self.__step_datas: List[StepData] = [] self.__session = self.__session or HttpSession() # save extracted variables of teststeps extracted_variables: VariablesMapping = {} # run teststeps for step in self.__teststeps: # override variables # step variables > extracted variables from previous steps step.variables = merge_variables(step.variables, extracted_variables) # step variables > testcase config variables step.variables = merge_variables(step.variables, self.__config.variables) # parse variables step.variables = parse_variables_mapping( step.variables, self.__project_meta.functions) while True: # run step if USE_ALLURE: with allure.step(f"step: {step.name}"): extract_mapping = self.__run_step(step) else: extract_mapping = self.__run_step(step) if step.retry_whens: variables_mapping = step.variables variables_mapping.update(extract_mapping) try: response = step.variables.get( 'response') or ResponseObject(requests.Response()) if isinstance(response, ResponseObject): response.validate(step.retry_whens, variables_mapping, self.__project_meta.functions) else: break except ValidationFailure: break else: break # save extracted variables to session variables extracted_variables.update(extract_mapping) self.__session_variables.update(extracted_variables) self.__duration = time.time() - self.__start_at return self
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