def test_extract_response_fail(self): resp = requests.post(url="{}/anything".format(HTTPBIN_SERVER), json={ 'success': False, "person": { "name": { "first_name": "Leo", "last_name": "Lee", }, "age": 29, "cities": ["Guangzhou", "Shenzhen"] } }) extract_binds_list = [{ "resp_content_dict_key_error": "content.not_exist" }] resp_obj = response.ResponseObject(resp) with self.assertRaises(exceptions.ExtractFailure): resp_obj.extract_response(extract_binds_list) extract_binds_list = [{ "resp_content_list_index_error": "content.person.cities.3" }] resp_obj = response.ResponseObject(resp) with self.assertRaises(exceptions.ExtractFailure): resp_obj.extract_response(extract_binds_list)
def test_extract_response_empty(self): resp = requests.post(url="{}/anything".format(HTTPBIN_SERVER), data="abc") extract_binds_list = [{"resp_content_body": "content.data"}] resp_obj = response.ResponseObject(resp) extract_binds_dict = resp_obj.extract_response(extract_binds_list) self.assertEqual(extract_binds_dict["resp_content_body"], 'abc') extract_binds_list = [{"resp_content_body": "content.data.def"}] resp_obj = response.ResponseObject(resp) with self.assertRaises(exceptions.ExtractFailure): resp_obj.extract_response(extract_binds_list)
def test_extract_text_response_exception(self): resp = requests.post(url="{}/anything".format(HTTPBIN_SERVER), data="LB123abcRB789") extract_binds_list = [{"resp_content_key1": "LB123.*RB789"}] resp_obj = response.ResponseObject(resp) with self.assertRaises(exceptions.ParamsError): resp_obj.extract_response(extract_binds_list)
def test_extract_response_json_string(self): resp = requests.post(url="{}/anything".format(HTTPBIN_SERVER), data="abc") extract_binds_list = [{"resp_content_body": "content.data"}] resp_obj = response.ResponseObject(resp) extract_binds_dict = resp_obj.extract_response(extract_binds_list) self.assertEqual(extract_binds_dict["resp_content_body"], "abc")
def test_parse_response_object_json(self): url = "http://127.0.0.1:5000/api/users" resp = requests.get(url) resp_obj = response.ResponseObject(resp) self.assertTrue(hasattr(resp_obj, 'status_code')) self.assertTrue(hasattr(resp_obj, 'headers')) self.assertTrue(hasattr(resp_obj, 'content')) self.assertIn('Content-Type', resp_obj.headers) self.assertIn('Content-Length', resp_obj.headers) self.assertIn('success', resp_obj.json)
def test_extract_response_others(self): resp = requests.get(url="{}/status/200".format(HTTPBIN_SERVER)) resp_obj = response.ResponseObject(resp) extract_binds_list = [{ "resp_others_encoding": "encoding" }, { "resp_others_history": "history" }] with self.assertRaises(exceptions.ParamsError): resp_obj.extract_response(extract_binds_list)
def test_extract_response_cookies(self): resp = requests.get(url="{}/cookies".format(HTTPBIN_SERVER), headers={"accept": "application/json"}) resp_obj = response.ResponseObject(resp) extract_binds_list = [{"resp_cookies": "cookies"}] extract_binds_dict = resp_obj.extract_response(extract_binds_list) self.assertEqual(extract_binds_dict["resp_cookies"], {}) extract_binds_list = [{"resp_cookies": "cookies.xx"}] with self.assertRaises(exceptions.ExtractFailure): resp_obj.extract_response(extract_binds_list)
def test_extract_response_status_code(self): resp = requests.get(url="{}/status/200".format(HTTPBIN_SERVER)) resp_obj = response.ResponseObject(resp) extract_binds_list = [{"resp_status_code": "status_code"}] extract_binds_dict = resp_obj.extract_response(extract_binds_list) self.assertEqual(extract_binds_dict["resp_status_code"], 200) extract_binds_list = [{"resp_status_code": "status_code.xx"}] with self.assertRaises(exceptions.ParamsError): resp_obj.extract_response(extract_binds_list)
def test_extract_response_body_html(self): resp = requests.get(url=HTTPBIN_SERVER) resp_obj = response.ResponseObject(resp) extract_binds_list = [{"resp_content": "content"}] extract_binds_dict = resp_obj.extract_response(extract_binds_list) self.assertIsInstance(extract_binds_dict["resp_content"], basestring) self.assertIn("httpbin.org", extract_binds_dict["resp_content"]) extract_binds_list = [{"resp_content": "content.xxx"}] with self.assertRaises(exceptions.ExtractFailure): resp_obj.extract_response(extract_binds_list)
def test_extract_text_response(self): resp = requests.post(url="{}/anything".format(HTTPBIN_SERVER), data="LB123abcRB789") extract_binds_list = [{ "resp_content_key1": "LB123(.*)RB789" }, { "resp_content_key2": "LB[\d]*(.*)RB[\d]*" }, { "resp_content_key3": "LB[\d]*(.*)9" }] resp_obj = response.ResponseObject(resp) extract_binds_dict = resp_obj.extract_response(extract_binds_list) self.assertEqual(extract_binds_dict["resp_content_key1"], "abc") self.assertEqual(extract_binds_dict["resp_content_key2"], "abc") self.assertEqual(extract_binds_dict["resp_content_key3"], "abcRB78")
def test_extract_response_elapsed(self): resp = requests.post(url="{}/anything".format(HTTPBIN_SERVER), json={ 'success': False, "person": { "name": { "first_name": "Leo", "last_name": "Lee", }, "age": 29, "cities": ["Guangzhou", "Shenzhen"] } }) resp_obj = response.ResponseObject(resp) extract_binds_list = [{"resp_elapsed": "elapsed"}] with self.assertRaises(exceptions.ParamsError): resp_obj.extract_response(extract_binds_list) extract_binds_list = [{ "resp_elapsed_microseconds": "elapsed.microseconds" }, { "resp_elapsed_seconds": "elapsed.seconds" }, { "resp_elapsed_days": "elapsed.days" }, { "resp_elapsed_total_seconds": "elapsed.total_seconds" }] extract_binds_dict = resp_obj.extract_response(extract_binds_list) self.assertGreater(extract_binds_dict["resp_elapsed_microseconds"], 1000) self.assertLess(extract_binds_dict["resp_elapsed_seconds"], 60) self.assertEqual(extract_binds_dict["resp_elapsed_days"], 0) self.assertGreater(extract_binds_dict["resp_elapsed_total_seconds"], 0) extract_binds_list = [{"resp_elapsed": "elapsed.years"}] with self.assertRaises(exceptions.ParamsError): resp_obj.extract_response(extract_binds_list)
def test_extract_response_encoding_ok_reason_url(self): resp = requests.get(url="{}/status/200".format(HTTPBIN_SERVER)) resp_obj = response.ResponseObject(resp) extract_binds_list = [{ "resp_encoding": "encoding" }, { "resp_ok": "ok" }, { "resp_reason": "reason" }, { "resp_url": "url" }] extract_binds_dict = resp_obj.extract_response(extract_binds_list) self.assertEqual(extract_binds_dict["resp_encoding"], "utf-8") self.assertEqual(extract_binds_dict["resp_ok"], True) self.assertEqual(extract_binds_dict["resp_reason"], "OK") self.assertEqual(extract_binds_dict["resp_url"], "{}/status/200".format(HTTPBIN_SERVER)) extract_binds_list = [{"resp_encoding": "encoding.xx"}] with self.assertRaises(exceptions.ParamsError): resp_obj.extract_response(extract_binds_list) extract_binds_list = [{"resp_ok": "ok.xx"}] with self.assertRaises(exceptions.ParamsError): resp_obj.extract_response(extract_binds_list) extract_binds_list = [{"resp_reason": "reason.xx"}] with self.assertRaises(exceptions.ParamsError): resp_obj.extract_response(extract_binds_list) extract_binds_list = [{"resp_url": "url.xx"}] with self.assertRaises(exceptions.ParamsError): resp_obj.extract_response(extract_binds_list)
def test_extract_response_headers(self): resp = requests.get(url="{}/status/200".format(HTTPBIN_SERVER)) resp_obj = response.ResponseObject(resp) extract_binds_list = [{ "resp_headers": "headers" }, { "resp_headers_content_type": "headers.Content-Type" }, { "resp_headers_content_type_lowercase": "headers.content-type" }] extract_binds_dict = resp_obj.extract_response(extract_binds_list) self.assertIn("Content-Type", extract_binds_dict["resp_headers"]) self.assertIn("text/html", extract_binds_dict["resp_headers_content_type"]) self.assertIn( "text/html", extract_binds_dict["resp_headers_content_type_lowercase"]) extract_binds_list = [{"resp_headers_xxx": "headers.xxx"}] with self.assertRaises(exceptions.ExtractFailure): resp_obj.extract_response(extract_binds_list)
def test_parse_response_object_content(self): url = "http://127.0.0.1:5000/" resp = requests.get(url) resp_obj = response.ResponseObject(resp) self.assertEqual(bytes, type(resp_obj.content))
def test_extract_response_body_json(self): resp = requests.post(url="{}/anything".format(HTTPBIN_SERVER), json={ 'success': False, "person": { "name": { "first_name": "Leo", "last_name": "Lee", }, "age": 29, "cities": ["Guangzhou", "Shenzhen"] } }) # resp.json() # { # "args": {}, # "data": "{\"success\": false, \"person\": {\"name\": {\"first_name\": \"Leo\", \"last_name\": \"Lee\"}, \"age\": 29, \"cities\": [\"Guangzhou\", \"Shenzhen\"]}}", # "files": {}, # "form": {}, # "headers": { # "Accept": "*/*", # "Accept-Encoding": "gzip, deflate", # "Connection": "keep-alive", # "Content-Length": "129", # "Content-Type": "application/json", # "Host": HTTPBIN_SERVER, # "User-Agent": "python-requests/2.18.4" # }, # "json": { # "person": { # "age": 29, # "cities": [ # "Guangzhou", # "Shenzhen" # ], # "name": { # "first_name": "Leo", # "last_name": "Lee" # } # }, # "success": false # }, # "method": "POST", # "origin": "127.0.0.1", # "url": "{}/anything".format(HTTPBIN_SERVER) # } extract_binds_list = [{ "resp_headers_content_type": "headers.content-type" }, { "resp_content_body_success": "json.json.success" }, { "resp_content_content_success": "content.json.success" }, { "resp_content_text_success": "text.json.success" }, { "resp_content_person_first_name": "content.json.person.name.first_name" }, { "resp_content_cities_1": "content.json.person.cities.1" }] resp_obj = response.ResponseObject(resp) extract_binds_dict = resp_obj.extract_response(extract_binds_list) self.assertEqual(extract_binds_dict["resp_headers_content_type"], "application/json") self.assertEqual(extract_binds_dict["resp_content_body_success"], False) self.assertEqual(extract_binds_dict["resp_content_content_success"], False) self.assertEqual(extract_binds_dict["resp_content_text_success"], False) self.assertEqual(extract_binds_dict["resp_content_person_first_name"], "Leo") self.assertEqual(extract_binds_dict["resp_content_cities_1"], "Shenzhen")
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 """ global tmp_extracted_variables # 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", {}) # override variables use former extracted_variables test_variables.update(tmp_extracted_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) # 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) # setup hooks setup_hooks = test_dict.get("setup_hooks", []) if setup_hooks: self.do_hook_actions(setup_hooks, "setup") 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!") # 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=parsed_url)) logger.log_debug( "request kwargs(raw): {kwargs}".format(kwargs=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) # extract extractors = test_dict.get("extract", {}) if extractors: extracted_variables_mapping = resp_obj.extract_response(extractors) tmp_extracted_variables.update(extracted_variables_mapping) self.session_context.update_session_variables( extracted_variables_mapping) self.session_context.update_session_variables(tmp_extracted_variables) # validate validators = test_dict.get("validate") or test_dict.get( "validators") or [] 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(parsed_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 # 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")