def test_query_json_content_is_text(self): json_content = "" query = "key" with self.assertRaises(exception.ResponseError): utils.query_json(json_content, query) json_content = "<html><body>content</body></html>" query = "key" with self.assertRaises(exception.ParseResponseError): utils.query_json(json_content, query)
def _extract_field_with_delimiter(self, field): """ response content could be json or html text. @param (str) field should be string joined by delimiter. e.g. "status_code" "content" "headers.content-type" "content.person.name.first_name" """ try: # string.split(sep=None, maxsplit=-1) -> list of strings # e.g. "content.person.name" => ["content", "person.name"] try: top_query, sub_query = field.split('.', 1) except ValueError: top_query = field sub_query = None if top_query in ["body", "content", "text"]: top_query_content = self.parsed_body() elif top_query == "cookies": cookies = self.resp_obj.cookies try: return cookies[sub_query] except KeyError: err_msg = u"Failed to extract attribute from cookies!\n" err_msg += u"cookies: {}\n".format(cookies) err_msg += u"attribute: {}".format(sub_query) logger.log_error(err_msg) raise exception.ParamsError(err_msg) else: try: top_query_content = getattr(self.resp_obj, top_query) except AttributeError: err_msg = u"Failed to extract attribute from response object: resp_obj.{}".format( top_query) logger.log_error(err_msg) raise exception.ParamsError(err_msg) if sub_query: if not isinstance(top_query_content, (dict, CaseInsensitiveDict, list)): err_msg = u"Failed to extract data with delimiter!\n" err_msg += u"response: {}\n".format(self.parsed_dict()) err_msg += u"regex: {}\n".format(field) logger.log_error(err_msg) raise exception.ParamsError(err_msg) # e.g. key: resp_headers_content_type, sub_query = "content-type" return utils.query_json(top_query_content, sub_query) else: # e.g. key: resp_status_code, resp_content return top_query_content except AttributeError: err_msg = u"Failed to extract value from response!\n" err_msg += u"response: {}\n".format(self.parsed_dict()) err_msg += u"extract field: {}\n".format(field) logger.log_error(err_msg) raise exception.ParamsError(err_msg)
def test_query_json(self): json_content = { "ids": [1, 2, 3, 4], "person": { "name": { "first_name": "Leo", "last_name": "Lee", }, "age": 29, "cities": ["Guangzhou", "Shenzhen"] } } query = "ids.2" result = utils.query_json(json_content, query) self.assertEqual(result, 3) query = "ids.str_key" with self.assertRaises(exception.ParseResponseError): utils.query_json(json_content, query) query = "ids.5" with self.assertRaises(exception.ParseResponseError): utils.query_json(json_content, query) query = "person.age" result = utils.query_json(json_content, query) self.assertEqual(result, 29) query = "person.not_exist_key" with self.assertRaises(exception.ParseResponseError): utils.query_json(json_content, query) query = "person.cities.0" result = utils.query_json(json_content, query) self.assertEqual(result, "Guangzhou") query = "person.name.first_name" result = utils.query_json(json_content, query) self.assertEqual(result, "Leo")
def _extract_field_with_delimiter(self, field): """ response content could be json or html text. Args: field (str): string joined by delimiter. e.g. "status_code" "headers" "cookies" "content" "headers.content-type" "content.person.name.first_name" """ # string.split(sep=None, maxsplit=1) -> list of strings # e.g. "content.person.name" => ["content", "person.name"] try: top_query, sub_query = field.split('.', 1) except ValueError: top_query = field sub_query = None # status_code if top_query in ["status_code", "encoding", "ok", "reason", "url"]: if sub_query: # status_code.XX err_msg = u"Failed to extract: {}\n".format(field) logger.log_error(err_msg) raise exceptions.ParamsError(err_msg) return getattr(self, top_query) # cookies elif top_query == "cookies": cookies = self.cookies if not sub_query: # extract cookies return cookies try: return cookies[sub_query] except KeyError: err_msg = u"Failed to extract cookie! => {}\n".format(field) err_msg += u"response cookies: {}\n".format(cookies) logger.log_error(err_msg) raise exceptions.ExtractFailure(err_msg) # elapsed elif top_query == "elapsed": available_attributes = u"available attributes: days, seconds, microseconds, total_seconds" if not sub_query: err_msg = u"elapsed is datetime.timedelta instance, attribute should also be specified!\n" err_msg += available_attributes logger.log_error(err_msg) raise exceptions.ParamsError(err_msg) elif sub_query in ["days", "seconds", "microseconds"]: return getattr(self.elapsed, sub_query) elif sub_query == "total_seconds": return self.elapsed.total_seconds() else: err_msg = "{} is not valid datetime.timedelta attribute.\n".format( sub_query) err_msg += available_attributes logger.log_error(err_msg) raise exceptions.ParamsError(err_msg) # req_headers elif top_query == "req_headers": headers = self.resp_obj.request.headers if not sub_query: # extract headers return headers try: return headers[sub_query] except KeyError: err_msg = u"Failed to extract req_header! => {}\n".format( field) err_msg += u"response headers: {}\n".format(headers) logger.log_error(err_msg) raise exceptions.ExtractFailure(err_msg) # headers elif top_query == "headers": headers = self.headers if not sub_query: # extract headers return headers try: return headers[sub_query] except KeyError: err_msg = u"Failed to extract header! => {}\n".format(field) err_msg += u"response headers: {}\n".format(headers) logger.log_error(err_msg) raise exceptions.ExtractFailure(err_msg) # response body elif top_query in ["body", "content", "text", "json"]: try: body = self.json except exceptions.JSONDecodeError: body = self.text if not sub_query: # extract response body return self.content # return body if isinstance(body, (dict, list)): # content = {"xxx": 123}, content.xxx return utils.query_json(body, sub_query) elif sub_query.isdigit(): # content = "abcdefg", content.3 => d return utils.query_json(body, sub_query) else: # content = "<html>abcdefg</html>", content.xxx err_msg = u"Failed to extract attribute from response body! => {}\n".format( field) err_msg += u"response body: {}\n".format(body) logger.log_error(err_msg) raise exceptions.ExtractFailure(err_msg) # new set response attributes in teardown_hooks elif top_query in self.__dict__: attributes = self.__dict__[top_query] if not sub_query: # extract response attributes return attributes if isinstance(attributes, (dict, list)): # attributes = {"xxx": 123}, content.xxx return utils.query_json(attributes, sub_query) elif sub_query.isdigit(): # attributes = "abcdefg", attributes.3 => d return utils.query_json(attributes, sub_query) else: # content = "attributes.new_attribute_not_exist" err_msg = u"Failed to extract cumstom set attribute from teardown hooks! => {}\n".format( field) err_msg += u"response set attributes: {}\n".format(attributes) logger.log_error(err_msg) raise exceptions.TeardownHooksFailure(err_msg) # others else: err_msg = u"Failed to extract attribute from response! => {}\n".format( field) err_msg += u"available response attributes: status_code, cookies, elapsed, headers, content, " \ u"text, json, encoding, ok, reason, url.\n\n" err_msg += u"If you want to set attribute in teardown_hooks, take the following example as reference:\n" err_msg += u"response.new_attribute = 'new_attribute_value'\n" logger.log_error(err_msg) raise exceptions.ParamsError(err_msg)
def _extract_field_with_delimiter(self, field): """ response content could be json or html text. @param (str) field should be string joined by delimiter. e.g. "status_code" "headers" "cookies" "content" "headers.content-type" "content.person.name.first_name" """ try: # string.split(sep=None, maxsplit=-1) -> list of strings # e.g. "content.person.name" => ["content", "person.name"] try: top_query, sub_query = field.split('.', 1) except ValueError: top_query = field sub_query = None if top_query == "cookies": cookies = self.cookies try: return cookies[sub_query] except KeyError: err_msg = u"Failed to extract attribute from cookies!\n" err_msg += u"cookies: {}\n".format(cookies) err_msg += u"attribute: {}".format(sub_query) logger.log_error(err_msg) raise exception.ParamsError(err_msg) try: top_query_content = getattr(self, top_query) except AttributeError: err_msg = u"Failed to extract attribute from response object: resp_obj.{}".format(top_query) logger.log_error(err_msg) raise exception.ParamsError(err_msg) if sub_query: if not isinstance(top_query_content, (dict, CaseInsensitiveDict, list)): try: # TODO: remove compatibility for content, text if isinstance(top_query_content, bytes): top_query_content = top_query_content.decode("utf-8") if isinstance(top_query_content, PreparedRequest): top_query_content = top_query_content.__dict__ else: top_query_content = json.loads(top_query_content) except json.decoder.JSONDecodeError: err_msg = u"Failed to extract data with delimiter!\n" err_msg += u"response content: {}\n".format(self.content) err_msg += u"regex: {}\n".format(field) logger.log_error(err_msg) raise exception.ParamsError(err_msg) # e.g. key: resp_headers_content_type, sub_query = "content-type" return utils.query_json(top_query_content, sub_query) else: # e.g. key: resp_status_code, resp_content return top_query_content except AttributeError: err_msg = u"Failed to extract value from response!\n" err_msg += u"response content: {}\n".format(self.content) err_msg += u"extract field: {}\n".format(field) logger.log_error(err_msg) raise exception.ParamsError(err_msg)
def _extract_field_with_delimiter(self, field): """ response content could be json or html text. @param (str) field should be string joined by delimiter. e.g. "status_code" "headers" "cookies" "content" "headers.content-type" "content.person.name.first_name" """ # string.split(sep=None, maxsplit=-1) -> list of strings # e.g. "content.person.name" => ["content", "person.name"] try: top_query, sub_query = field.split('.', 1) except ValueError: top_query = field sub_query = None # status_code if top_query in ["status_code", "encoding", "ok", "reason", "url"]: if sub_query: # status_code.XX err_msg = u"Failed to extract: {}\n".format(field) logger.log_error(err_msg) raise exceptions.ParamsError(err_msg) return getattr(self, top_query) # cookies elif top_query == "cookies": cookies = self.cookies.get_dict() if not sub_query: # extract cookies return cookies try: return cookies[sub_query] except KeyError: err_msg = u"Failed to extract cookie! => {}\n".format(field) err_msg += u"response cookies: {}\n".format(cookies) logger.log_error(err_msg) raise exceptions.ExtractFailure(err_msg) # elapsed elif top_query == "elapsed": available_attributes = u"available attributes: days, seconds, microseconds, total_seconds" if not sub_query: err_msg = u"elapsed is datetime.timedelta instance, attribute should also be specified!\n" err_msg += available_attributes logger.log_error(err_msg) raise exceptions.ParamsError(err_msg) elif sub_query in ["days", "seconds", "microseconds"]: return getattr(self.elapsed, sub_query) elif sub_query == "total_seconds": return self.elapsed.total_seconds() else: err_msg = "{} is not valid datetime.timedelta attribute.\n".format( sub_query) err_msg += available_attributes logger.log_error(err_msg) raise exceptions.ParamsError(err_msg) # headers elif top_query == "headers": headers = self.headers if not sub_query: # extract headers return headers try: return headers[sub_query] except KeyError: err_msg = u"Failed to extract header! => {}\n".format(field) err_msg += u"response headers: {}\n".format(headers) logger.log_error(err_msg) raise exceptions.ExtractFailure(err_msg) # response body elif top_query in ["content", "text", "json"]: try: body = self.json except exceptions.JSONDecodeError: body = self.text if not sub_query: # extract response body return body if isinstance(body, (dict, list)): # content = {"xxx": 123}, content.xxx return utils.query_json(body, sub_query) elif sub_query.isdigit(): # content = "abcdefg", content.3 => d return utils.query_json(body, sub_query) else: # content = "<html>abcdefg</html>", content.xxx err_msg = u"Failed to extract attribute from response body! => {}\n".format( field) err_msg += u"response body: {}\n".format(body) logger.log_error(err_msg) raise exceptions.ExtractFailure(err_msg) # response jsonpath elif top_query == 'jsonpath': try: body = self.json except exceptions.JSONDecodeError: body = self.text if not sub_query: # extract response body return body re = jsonpath.jsonpath(body, expr=sub_query) if re: # return first value of result(list) return re[0] else: return 'null' # others else: err_msg = u"Failed to extract attribute from response! => {}\n".format( field) err_msg += u"available response attributes: status_code, cookies, elapsed, headers, content, text, json, encoding, ok, reason, url." logger.log_error(err_msg) raise exceptions.ParamsError(err_msg)
def _extract_field_with_delimiter(self, field): """ response content could be json or html text. @param (str) field should be string joined by delimiter. e.g. "status_code" "headers" "cookies" "content" "headers.content-type" "content.person.name.first_name" """ try: # string.split(sep=None, maxsplit=-1) -> list of strings # e.g. "content.person.name" => ["content", "person.name"] try: top_query, sub_query = field.split('.', 1) except ValueError: top_query = field sub_query = None if top_query == "cookies": cookies = self.cookies try: return cookies[sub_query] except KeyError: err_msg = u"Failed to extract attribute from cookies!\n" err_msg += u"cookies: {}\n".format(cookies) err_msg += u"attribute: {}".format(sub_query) logger.log_error(err_msg) raise exception.ParamsError(err_msg) elif top_query == "elapsed": if sub_query in ["days", "seconds", "microseconds"]: return getattr(self.elapsed, sub_query) elif sub_query == "total_seconds": return self.elapsed.total_seconds() else: err_msg = "{}: {} is not valid timedelta attribute.\n".format( field, sub_query) err_msg += "elapsed only support attributes: days, seconds, microseconds, total_seconds.\n" logger.log_error(err_msg) raise exception.ParamsError(err_msg) try: top_query_content = getattr(self, top_query) except AttributeError: err_msg = u"Failed to extract attribute from response object: resp_obj.{}".format( top_query) logger.log_error(err_msg) raise exception.ParamsError(err_msg) if sub_query: if not isinstance(top_query_content, (dict, CaseInsensitiveDict, list)): try: # TODO: remove compatibility for content, text if isinstance(top_query_content, bytes): top_query_content = top_query_content.decode( "utf-8") if isinstance(top_query_content, PreparedRequest): top_query_content = top_query_content.__dict__ else: top_query_content = json.loads(top_query_content) except json.decoder.JSONDecodeError: err_msg = u"Failed to extract data with delimiter!\n" err_msg += u"response content: {}\n".format( self.content) err_msg += u"regex: {}\n".format(field) logger.log_error(err_msg) raise exception.ParamsError(err_msg) # e.g. key: resp_headers_content_type, sub_query = "content-type" return utils.query_json(top_query_content, sub_query) else: # e.g. key: resp_status_code, resp_content return top_query_content except AttributeError: err_msg = u"Failed to extract value from response!\n" err_msg += u"response content: {}\n".format(self.content) err_msg += u"extract field: {}\n".format(field) logger.log_error(err_msg) raise exception.ParamsError(err_msg)