def test_handle_config_key_case(self): origin_dict = { "Name": "test", "Request": { "url": "http://127.0.0.1:5000", "METHOD": "POST", "Headers": { "Accept": "application/json", "User-Agent": "ios/9.3" } } } new_dict = utils.lower_test_dict_keys(origin_dict) self.assertIn("name", new_dict) self.assertIn("request", new_dict) self.assertIn("method", new_dict["request"]) self.assertIn("headers", new_dict["request"]) self.assertIn("Accept", new_dict["request"]["headers"]) self.assertIn("User-Agent", new_dict["request"]["headers"]) origin_dict = { "Name": "test", "Request": "$default_request" } new_dict = utils.lower_test_dict_keys(origin_dict) self.assertIn("$default_request", new_dict["request"])
def init_test(self, test_dict, level): """ create/update context variables binds Args: test_dict (dict): level (enum): "testcase" or "teststep" testcase: { "name": "testcase description", "variables": [], # optional "request": { "base_url": "http://127.0.0.1:5000", "headers": { "User-Agent": "iOS/2.8.3" } } } teststep: { "name": "teststep description", "variables": [], # optional "request": { "url": "/api/get-token", "method": "POST", "headers": { "Content-Type": "application/json" } }, "json": { "sign": "f1219719911caae89ccc301679857ebfda115ca2" } } Returns: dict: parsed request dict """ test_dict = utils.lower_test_dict_keys(test_dict) self.context.init_context_variables(level) variables = test_dict.get('variables') \ or test_dict.get('variable_binds', OrderedDict()) self.context.update_context_variables(variables, level) request_config = test_dict.get('request', {}) parsed_request = self.context.get_parsed_request(request_config, level) base_url = parsed_request.pop("base_url", None) self.http_client_session = self.http_client_session or HttpSession( base_url) return parsed_request
def _run_single_test(self, test_dict): """ override run single teststep. Args: test_dict (dict): teststep info { "name": "teststep description", "skip": "skip this test unconditionally", "times": 3, "interface_type": "dubbo" "variables": [], # optional, override "request": { "url": "http://127.0.0.1:5000/api/users/1000", "method": "POST", "headers": { "Content-Type": "application/json", "authorization": "$authorization", "random": "$random" }, "json": {"name": "user", "password": "******"} }, "extract": {}, # optional "validate": [], # optional "setup_hooks": [], # optional "teardown_hooks": [] # optional } Raises: exceptions.ParamsError exceptions.ValidationFailure exceptions.ExtractFailure """ # prepare test_dict = utils.lower_test_dict_keys(test_dict) interface_type = test_dict.get('interface_type', '') if interface_type == "dubbo": result = self._run_dubbo_test(test_dict) else: result = self._run_http_test(test_dict) return result
def _run_test(self, test_dict): """ run single teststep. Args: test_dict (dict): teststep info { "name": "teststep description", "skip": "skip this test unconditionally", "times": 3, "variables": [], # optional, override "request": { "url": "http://127.0.0.1:5000/api/users/1000", "method": "POST", "headers": { "Content-Type": "application/json", "authorization": "$authorization", "random": "$random" }, "json": {"name": "user", "password": "******"} }, "extract": {}, # optional "validate": [], # optional "setup_hooks": [], # optional "teardown_hooks": [] # optional } Raises: exceptions.ParamsError exceptions.ValidationFailure exceptions.ExtractFailure """ # clear meta data first to ensure independence for each test self.__clear_test_data() # check skip self._handle_skip_feature(test_dict) # prepare test_dict = utils.lower_test_dict_keys(test_dict) test_variables = test_dict.get("variables", {}) self.session_context.init_test_variables(test_variables) # teststep name test_name = self.session_context.eval_content(test_dict.get( "name", "")) # parse test request raw_request = test_dict.get('request', {}) parsed_test_request = self.session_context.eval_content(raw_request) self.session_context.update_test_variables("request", parsed_test_request) # setup hooks setup_hooks = test_dict.get("setup_hooks", []) if setup_hooks: self.do_hook_actions(setup_hooks, HookTypeEnum.SETUP) # prepend url with base_url unless it's already an absolute URL url = parsed_test_request.pop('url') base_url = self.session_context.eval_content( test_dict.get("base_url", "")) parsed_url = utils.build_url(base_url, url) request_headers = parsed_test_request.setdefault("headers", {}) if "HRUN-Request-ID" not in request_headers: parsed_test_request["headers"]["HRUN-Request-ID"] = \ self.session_context.session_variables_mapping["HRUN-Request-ID"] try: method = parsed_test_request.pop('method') parsed_test_request.setdefault("verify", self.verify) group_name = parsed_test_request.pop("group", None) except KeyError: raise exceptions.ParamsError("URL or METHOD missed!") logger.info(f"{method} {parsed_url}") logger.debug(f"request kwargs(raw): {parsed_test_request}") # request resp = self.http_client_session.request(method, parsed_url, name=(group_name or test_name), **parsed_test_request) resp_obj = response.ResponseObject(resp) def log_req_resp_details(): err_msg = "{} DETAILED REQUEST & RESPONSE {}\n".format( "*" * 32, "*" * 32) # log request err_msg += "====== request details ======\n" err_msg += f"url: {parsed_url}\n" err_msg += f"method: {method}\n" headers = parsed_test_request.pop("headers", {}) err_msg += f"headers: {headers}\n" for k, v in parsed_test_request.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_obj.status_code}\n" err_msg += f"headers: {resp_obj.headers}\n" err_msg += f"body: {repr(resp_obj.text)}\n" logger.error(err_msg) # teardown hooks teardown_hooks = test_dict.get("teardown_hooks", []) if teardown_hooks: self.session_context.update_test_variables("response", resp_obj) self.do_hook_actions(teardown_hooks, HookTypeEnum.TEARDOWN) self.http_client_session.update_last_req_resp_record(resp_obj) # extract extractors = test_dict.get("extract", {}) try: extracted_variables_mapping = resp_obj.extract_response(extractors) self.session_context.update_session_variables( extracted_variables_mapping) except (exceptions.ParamsError, exceptions.ExtractFailure): log_req_resp_details() raise # validate validators = test_dict.get("validate") or test_dict.get( "validators") or [] validate_script = test_dict.get("validate_script", []) if validate_script: validators.append({ "type": "python_script", "script": validate_script }) validator = Validator(self.session_context, resp_obj) try: validator.validate(validators) except exceptions.ValidationFailure: log_req_resp_details() raise finally: self.validation_results = validator.validation_results
def _run_test(self, test_dict): """ run single teststep. Args: test_dict (dict): teststep info { "name": "teststep description", "skip": "skip this test unconditionally", "times": 3, "variables": [], # optional, override "request": { "url": "http://127.0.0.1:5000/api/users/1000", "method": "POST", "headers": { "Content-Type": "application/json", "authorization": "$authorization", "random": "$random" }, "json": {"name": "user", "password": "******"} }, "extract": {}, # optional "validate": [], # optional "setup_hooks": [], # optional "teardown_hooks": [] # optional } Raises: exceptions.ParamsError exceptions.ValidationFailure exceptions.ExtractFailure """ # clear meta data first to ensure independence for each test self.__clear_test_data() # check skip self._handle_skip_feature(test_dict) # prepare test_dict = utils.lower_test_dict_keys(test_dict) test_variables = test_dict.get("variables", {}) self.session_context.init_test_variables(test_variables) # teststep name test_name = test_dict.get("name", "") # parse test request raw_request = test_dict.get('request', {}) parsed_test_request = self.session_context.eval_content(raw_request) self.session_context.update_test_variables("request", parsed_test_request) # setup hooks setup_hooks = test_dict.get("setup_hooks", []) if setup_hooks: self.do_hook_actions(setup_hooks, "setup") try: url = parsed_test_request.pop('url') method = parsed_test_request.pop('method') parsed_test_request.setdefault("verify", self.verify) group_name = parsed_test_request.pop("group", None) except KeyError: raise exceptions.ParamsError("URL or METHOD missed!") # TODO: move method validation to json schema valid_methods = [ "GET", "HEAD", "POST", "PUT", "PATCH", "DELETE", "OPTIONS" ] if method.upper() not in valid_methods: err_msg = u"Invalid HTTP method! => {}\n".format(method) err_msg += "Available HTTP methods: {}".format( "/".join(valid_methods)) logger.log_error(err_msg) raise exceptions.ParamsError(err_msg) logger.log_info("{method} {url}".format(method=method, url=url)) logger.log_debug( "request kwargs(raw): {kwargs}".format(kwargs=parsed_test_request)) # request resp = self.http_client_session.request(method, url, name=(group_name or test_name), **parsed_test_request) resp_obj = response.ResponseObject(resp) # teardown hooks teardown_hooks = test_dict.get("teardown_hooks", []) if teardown_hooks: self.session_context.update_test_variables("response", resp_obj) self.do_hook_actions(teardown_hooks, "teardown") # extract extractors = test_dict.get("extract", {}) extracted_variables_mapping = resp_obj.extract_response(extractors) self.session_context.update_session_variables( extracted_variables_mapping) # validate validators = test_dict.get("validate", []) try: self.session_context.validate(validators, resp_obj) except (exceptions.ParamsError, exceptions.ValidationFailure, exceptions.ExtractFailure): err_msg = "{} DETAILED REQUEST & RESPONSE {}\n".format( "*" * 32, "*" * 32) # log request err_msg += "====== request details ======\n" err_msg += "url: {}\n".format(url) err_msg += "method: {}\n".format(method) err_msg += "headers: {}\n".format( parsed_test_request.pop("headers", {})) for k, v in parsed_test_request.items(): v = utils.omit_long_data(v) err_msg += "{}: {}\n".format(k, repr(v)) err_msg += "\n" # log response err_msg += "====== response details ======\n" err_msg += "status_code: {}\n".format(resp_obj.status_code) err_msg += "headers: {}\n".format(resp_obj.headers) err_msg += "body: {}\n".format(repr(resp_obj.text)) logger.log_error(err_msg) raise finally: self.validation_results = self.session_context.validation_results
def _run_dubbo_test(self, test_dict): # clear meta data first to ensure independence for each test self.__clear_test_data() # check skip self._handle_skip_feature(test_dict) # prepare test_dict = utils.lower_test_dict_keys(test_dict) test_variables = test_dict.get("variables", {}) self.session_context.init_test_variables(test_variables) # parse test request raw_request = test_dict.get('request', {}) parsed_test_request = self.session_context.eval_content(raw_request) self.session_context.update_test_variables("request", parsed_test_request) # prepend url with base_url unless it's already an absolute URL host = parsed_test_request.pop('host', '') port = parsed_test_request.pop('port', '') # setup hooks setup_hooks = test_dict.get("setup_hooks", []) if setup_hooks: self.do_hook_actions(setup_hooks, HookTypeEnum.SETUP) try: service = parsed_test_request.pop('service') method = parsed_test_request.pop('method') params = parsed_test_request.pop("params", "") parsed_test_request.setdefault("verify", self.verify) group_name = parsed_test_request.pop("group", None) except KeyError: raise exceptions.ParamsError("SERVICE or METHOD missed!") logger.log_info("{host}:{port} {service}.{method}".format( host=host, port=port, service=service, method=method)) logger.log_debug( "request kwargs(raw): {kwargs}".format(kwargs=parsed_test_request)) # request resp = self.dubbo_client_session.request( host, port, service, method, params, name=(group_name or self.session_context.eval_content( test_dict.get("name", ""))), **parsed_test_request) # TODO: responseObject resp_obj = DubboResponseObject(resp) def log_req_resp_details(): err_msg = "{} DETAILED REQUEST & RESPONSE {}\n".format( "*" * 32, "*" * 32) # log request err_msg += "====== request details ======\n" err_msg += "host: {}\n".format(host) err_msg += "port: {}\n".format(port) err_msg += "service: {}\n".format(service) err_msg += "method: {}\n".format(method) err_msg += "params: {}\n".format(params) for k, v in parsed_test_request.items(): v = utils.omit_long_data(v) err_msg += "{}: {}\n".format(k, repr(v)) err_msg += "\n" # log response err_msg += "====== response details ======\n" err_msg += "body: {}\n".format(repr(resp_obj.json)) logger.log_error(err_msg) # teardown hooks teardown_hooks = test_dict.get("teardown_hooks", []) if teardown_hooks: self.session_context.update_test_variables("response", resp_obj) self.do_hook_actions(teardown_hooks, HookTypeEnum.TEARDOWN) self.dubbo_client_session.update_last_req_resp_record(resp_obj) # extract extractors = test_dict.get("extract", {}) try: extracted_variables_mapping = resp_obj.extract_response(extractors) self.session_context.update_session_variables( extracted_variables_mapping) except (exceptions.ParamsError, exceptions.ExtractFailure): log_req_resp_details() raise # validate validators = test_dict.get("validate") or test_dict.get( "validators") or [] validate_script = test_dict.get("validate_script", []) if validate_script: validators.append({ "type": "python_script", "script": validate_script }) validator = Validator(self.session_context, resp_obj) try: validator.validate(validators) except exceptions.ValidationFailure: log_req_resp_details() raise return validator.validation_results
def _run_test_once(self, test_dict, wait_validators=None): # clear meta data first to ensure independence for each test self.__clear_test_data() # check skip self._handle_skip_feature(test_dict) # prepare test_dict = utils.lower_test_dict_keys(test_dict) test_variables = test_dict.get("variables", {}) self.session_context.init_test_variables(test_variables) # teststep name test_name = test_dict.get("name", "") # parse test request raw_request = test_dict.get('request', {}) parsed_test_request = self.session_context.eval_content(raw_request) self.session_context.update_test_variables("request", parsed_test_request) # setup hooks setup_hooks = test_dict.get("setup_hooks", []) if setup_hooks: self.do_hook_actions(setup_hooks, "setup") try: url = parsed_test_request.pop('url') method = parsed_test_request.pop('method') parsed_test_request.setdefault("verify", self.verify) group_name = parsed_test_request.pop("group", None) except KeyError: raise exceptions.ParamsError("URL or METHOD missed!") # TODO: move method validation to json schema valid_methods = [ "GET", "HEAD", "POST", "PUT", "PATCH", "DELETE", "OPTIONS" ] if method.upper() not in valid_methods: err_msg = u"Invalid HTTP method! => {}\n".format(method) err_msg += "Available HTTP methods: {}".format( "/".join(valid_methods)) logger.log_error(err_msg) raise exceptions.ParamsError(err_msg) logger.log_info("{method} {url}".format(method=method, url=url)) logger.log_debug( "request kwargs(raw): {kwargs}".format(kwargs=parsed_test_request)) # request resp = self.http_client_session.request(method, url, name=(group_name or test_name), **parsed_test_request) resp_obj = response.ResponseObject(resp) # teardown hooks teardown_hooks = test_dict.get("teardown_hooks", []) if teardown_hooks: self.session_context.update_test_variables("response", resp_obj) self.do_hook_actions(teardown_hooks, "teardown") # extract extractors = test_dict.get("extract", {}) extracted_variables_mapping = resp_obj.extract_response(extractors) self.session_context.update_session_variables( extracted_variables_mapping) # validate if wait_validators: wait_validate_pass, wait_failures = self.session_context.validate( wait_validators, resp_obj) if not wait_validate_pass: # err_msg = "{} DETAILED REQUEST & RESPONSE {}\n".format("*" * 32, "*" * 32) # # # log request # err_msg += "====== request details ======\n" # err_msg += "url: {}\n".format(url) # err_msg += "method: {}\n".format(method) # err_msg += "headers: {}\n".format(parsed_test_request.pop("headers", {})) # for k, v in parsed_test_request.items(): # v = utils.omit_long_data(v) # err_msg += "{}: {}\n".format(k, repr(v)) # err_msg += "\n" # log response # err_msg += "====== response details ======\n" # err_msg += "status_code: {}\n".format(resp_obj.status_code) # err_msg += "headers: {}\n".format(resp_obj.headers) # err_msg += "body: {}\n".format(repr(resp_obj.text)) # logger.log_error("During the wait: \n" + err_msg) logger.log_error( "====== During the wait: the expect conditions can not Meet the requirements! ======" ) failures_string = "\n".join( [failure for failure in wait_failures]) self.validation_results = self.session_context.validation_results raise exceptions.ValidationFailure(failures_string) validators = test_dict.get("validate", []) validate_pass, failures = self.session_context.validate( validators, resp_obj) self.validation_results = self.session_context.validation_results # try: # validate_pass, failures = self.session_context.validate(validators, resp_obj) # except (exceptions.ParamsError, exceptions.ValidationFailure, exceptions.ExtractFailure): # err_msg = "{} DETAILED REQUEST & RESPONSE {}\n".format("*" * 32, "*" * 32) # # # log request # err_msg += "====== request details ======\n" # err_msg += "url: {}\n".format(url) # err_msg += "method: {}\n".format(method) # err_msg += "headers: {}\n".format(parsed_test_request.pop("headers", {})) # for k, v in parsed_test_request.items(): # v = utils.omit_long_data(v) # err_msg += "{}: {}\n".format(k, repr(v)) # # err_msg += "\n" # # # log response # err_msg += "====== response details ======\n" # err_msg += "status_code: {}\n".format(resp_obj.status_code) # err_msg += "headers: {}\n".format(resp_obj.headers) # err_msg += "body: {}\n".format(repr(resp_obj.text)) # logger.log_error(err_msg) # raise # finally: # self.validation_results = self.session_context.validation_results return validate_pass, failures