mirror of
https://github.com/httprunner/httprunner.git
synced 2026-05-13 08:59:44 +08:00
create ResponseObject, each test result will be associated with a ResponseObject
This commit is contained in:
153
ate/response.py
153
ate/response.py
@@ -1,93 +1,100 @@
|
||||
from ate import utils, exception
|
||||
|
||||
|
||||
def parse_response_body(resp_obj):
|
||||
try:
|
||||
return resp_obj.json()
|
||||
except ValueError:
|
||||
return resp_obj.text
|
||||
class ResponseObject(object):
|
||||
|
||||
def parse_response_object(resp_obj):
|
||||
return {
|
||||
'status_code': resp_obj.status_code,
|
||||
'headers': resp_obj.headers,
|
||||
'body': parse_response_body(resp_obj)
|
||||
}
|
||||
def __init__(self, resp_obj):
|
||||
""" initialize with a requests.Response object
|
||||
@param (requests.Response instance) resp_obj
|
||||
"""
|
||||
self.resp_obj = resp_obj
|
||||
|
||||
def diff_response(resp_obj, expected_resp_json):
|
||||
diff_content = {}
|
||||
resp_info = parse_response_object(resp_obj)
|
||||
def parse_response_body(self):
|
||||
try:
|
||||
return self.resp_obj.json()
|
||||
except ValueError:
|
||||
return self.resp_obj.text
|
||||
|
||||
expected_status_code = expected_resp_json.get('status_code', 200)
|
||||
if resp_info['status_code'] != int(expected_status_code):
|
||||
diff_content['status_code'] = {
|
||||
'value': resp_info['status_code'],
|
||||
'expected': expected_status_code
|
||||
def parse_response_object(self):
|
||||
return {
|
||||
'status_code': self.resp_obj.status_code,
|
||||
'headers': self.resp_obj.headers,
|
||||
'body': self.parse_response_body()
|
||||
}
|
||||
|
||||
expected_headers = expected_resp_json.get('headers', {})
|
||||
headers_diff = utils.diff_json(resp_info['headers'], expected_headers)
|
||||
if headers_diff:
|
||||
diff_content['headers'] = headers_diff
|
||||
def diff_response(self, expected_resp_json):
|
||||
diff_content = {}
|
||||
resp_info = self.parse_response_object()
|
||||
|
||||
expected_body = expected_resp_json.get('body', None)
|
||||
expected_status_code = expected_resp_json.get('status_code', 200)
|
||||
if resp_info['status_code'] != int(expected_status_code):
|
||||
diff_content['status_code'] = {
|
||||
'value': resp_info['status_code'],
|
||||
'expected': expected_status_code
|
||||
}
|
||||
|
||||
if expected_body is None:
|
||||
body_diff = {}
|
||||
elif type(expected_body) != type(resp_info['body']):
|
||||
body_diff = {
|
||||
'value': resp_info['body'],
|
||||
'expected': expected_body
|
||||
}
|
||||
elif isinstance(expected_body, str):
|
||||
if expected_body != resp_info['body']:
|
||||
expected_headers = expected_resp_json.get('headers', {})
|
||||
headers_diff = utils.diff_json(resp_info['headers'], expected_headers)
|
||||
if headers_diff:
|
||||
diff_content['headers'] = headers_diff
|
||||
|
||||
expected_body = expected_resp_json.get('body', None)
|
||||
|
||||
if expected_body is None:
|
||||
body_diff = {}
|
||||
elif type(expected_body) != type(resp_info['body']):
|
||||
body_diff = {
|
||||
'value': resp_info['body'],
|
||||
'expected': expected_body
|
||||
}
|
||||
elif isinstance(expected_body, dict):
|
||||
body_diff = utils.diff_json(resp_info['body'], expected_body)
|
||||
elif isinstance(expected_body, str):
|
||||
if expected_body != resp_info['body']:
|
||||
body_diff = {
|
||||
'value': resp_info['body'],
|
||||
'expected': expected_body
|
||||
}
|
||||
elif isinstance(expected_body, dict):
|
||||
body_diff = utils.diff_json(resp_info['body'], expected_body)
|
||||
|
||||
if body_diff:
|
||||
diff_content['body'] = body_diff
|
||||
if body_diff:
|
||||
diff_content['body'] = body_diff
|
||||
|
||||
return diff_content
|
||||
return diff_content
|
||||
|
||||
def extract_response(resp_obj, context, delimiter='.'):
|
||||
""" extract content from requests.Response, and bind extracted value to context.extractors
|
||||
@param (requests.Response instance) resp_obj
|
||||
@param (ate.context.Context instance) context
|
||||
context.extractors:
|
||||
{
|
||||
"resp_status_code": "status_code",
|
||||
"resp_headers_content_type": "headers.content-type",
|
||||
"resp_content": "content",
|
||||
"resp_content_person_first_name": "content.person.name.first_name"
|
||||
}
|
||||
"""
|
||||
for key, value in context.extractors.items():
|
||||
try:
|
||||
if isinstance(value, str):
|
||||
value += "."
|
||||
# string.split(sep=None, maxsplit=-1) -> list of strings
|
||||
# e.g. "content.person.name" => ["content", "person.name"]
|
||||
top_query, sub_query = value.split(delimiter, 1)
|
||||
def extract_response(self, context, delimiter='.'):
|
||||
""" extract content from requests.Response, and bind extracted value to context.extractors
|
||||
@param (ate.context.Context instance) context
|
||||
context.extractors:
|
||||
{
|
||||
"resp_status_code": "status_code",
|
||||
"resp_headers_content_type": "headers.content-type",
|
||||
"resp_content": "content",
|
||||
"resp_content_person_first_name": "content.person.name.first_name"
|
||||
}
|
||||
"""
|
||||
for key, value in context.extractors.items():
|
||||
try:
|
||||
if isinstance(value, str):
|
||||
value += "."
|
||||
# string.split(sep=None, maxsplit=-1) -> list of strings
|
||||
# e.g. "content.person.name" => ["content", "person.name"]
|
||||
top_query, sub_query = value.split(delimiter, 1)
|
||||
|
||||
if top_query in ["body", "content", "text"]:
|
||||
json_content = self.parse_response_body()
|
||||
else:
|
||||
json_content = getattr(self.resp_obj, top_query)
|
||||
|
||||
if sub_query:
|
||||
# e.g. key: resp_headers_content_type, sub_query = "content-type"
|
||||
answer = utils.query_json(json_content, sub_query)
|
||||
context.extractors[key] = answer
|
||||
else:
|
||||
# e.g. key: resp_status_code, resp_content
|
||||
context.extractors[key] = json_content
|
||||
|
||||
if top_query in ["body", "content", "text"]:
|
||||
json_content = parse_response_body(resp_obj)
|
||||
else:
|
||||
json_content = getattr(resp_obj, top_query)
|
||||
raise NotImplementedError("TODO: support template.")
|
||||
|
||||
if sub_query:
|
||||
# e.g. key: resp_headers_content_type, sub_query = "content-type"
|
||||
answer = utils.query_json(json_content, sub_query)
|
||||
context.extractors[key] = answer
|
||||
else:
|
||||
# e.g. key: resp_status_code, resp_content
|
||||
context.extractors[key] = json_content
|
||||
|
||||
else:
|
||||
raise NotImplementedError("TODO: support template.")
|
||||
|
||||
except AttributeError:
|
||||
raise exception.ParamsError("invalid extract_binds!")
|
||||
except AttributeError:
|
||||
raise exception.ParamsError("invalid extract_binds!")
|
||||
|
||||
@@ -103,9 +103,11 @@ class TestRunner(object):
|
||||
except KeyError:
|
||||
raise exception.ParamsError("URL or METHOD missed!")
|
||||
|
||||
resp_obj = self.client.request(url=url, method=method, **req_kwargs)
|
||||
response.extract_response(resp_obj, self.context)
|
||||
diff_content = response.diff_response(resp_obj, testcase['response'])
|
||||
resp = self.client.request(url=url, method=method, **req_kwargs)
|
||||
|
||||
resp_obj = response.ResponseObject(resp)
|
||||
resp_obj.extract_response(self.context)
|
||||
diff_content = resp_obj.diff_response(testcase['response'])
|
||||
success = False if diff_content else True
|
||||
return success, diff_content
|
||||
|
||||
|
||||
@@ -7,8 +7,9 @@ class TestResponse(ApiServerUnittest):
|
||||
|
||||
def test_parse_response_object_json(self):
|
||||
url = "http://127.0.0.1:5000/api/users"
|
||||
resp_obj = requests.get(url)
|
||||
parse_result = response.parse_response_object(resp_obj)
|
||||
resp = requests.get(url)
|
||||
resp_obj = response.ResponseObject(resp)
|
||||
parse_result = resp_obj.parse_response_object()
|
||||
self.assertIn('status_code', parse_result)
|
||||
self.assertIn('headers', parse_result)
|
||||
self.assertIn('body', parse_result)
|
||||
@@ -18,8 +19,9 @@ class TestResponse(ApiServerUnittest):
|
||||
|
||||
def test_parse_response_object_text(self):
|
||||
url = "http://127.0.0.1:5000/"
|
||||
resp_obj = requests.get(url)
|
||||
parse_result = response.parse_response_object(resp_obj)
|
||||
resp = requests.get(url)
|
||||
resp_obj = response.ResponseObject(resp)
|
||||
parse_result = resp_obj.parse_response_object()
|
||||
self.assertIn('status_code', parse_result)
|
||||
self.assertIn('headers', parse_result)
|
||||
self.assertIn('body', parse_result)
|
||||
@@ -29,7 +31,7 @@ class TestResponse(ApiServerUnittest):
|
||||
|
||||
def test_diff_response_status_code_equal(self):
|
||||
status_code = random.randint(200, 511)
|
||||
resp_obj = requests.post(
|
||||
resp = requests.post(
|
||||
url="http://127.0.0.1:5000/customize-response",
|
||||
json={
|
||||
'status_code': status_code,
|
||||
@@ -39,12 +41,13 @@ class TestResponse(ApiServerUnittest):
|
||||
expected_resp_json = {
|
||||
'status_code': status_code
|
||||
}
|
||||
diff_content = response.diff_response(resp_obj, expected_resp_json)
|
||||
resp_obj = response.ResponseObject(resp)
|
||||
diff_content = resp_obj.diff_response(expected_resp_json)
|
||||
self.assertFalse(diff_content)
|
||||
|
||||
def test_diff_response_status_code_not_equal(self):
|
||||
status_code = random.randint(200, 511)
|
||||
resp_obj = requests.post(
|
||||
resp = requests.post(
|
||||
url="http://127.0.0.1:5000/customize-response",
|
||||
json={
|
||||
'status_code': status_code,
|
||||
@@ -54,14 +57,15 @@ class TestResponse(ApiServerUnittest):
|
||||
expected_resp_json = {
|
||||
'status_code': 512
|
||||
}
|
||||
diff_content = response.diff_response(resp_obj, expected_resp_json)
|
||||
resp_obj = response.ResponseObject(resp)
|
||||
diff_content = resp_obj.diff_response(expected_resp_json)
|
||||
self.assertIn('value', diff_content['status_code'])
|
||||
self.assertIn('expected', diff_content['status_code'])
|
||||
self.assertEqual(diff_content['status_code']['value'], status_code)
|
||||
self.assertEqual(diff_content['status_code']['expected'], 512)
|
||||
|
||||
def test_diff_response_headers_equal(self):
|
||||
resp_obj = requests.post(
|
||||
resp = requests.post(
|
||||
url="http://127.0.0.1:5000/customize-response",
|
||||
json={
|
||||
'headers': {
|
||||
@@ -77,11 +81,12 @@ class TestResponse(ApiServerUnittest):
|
||||
'def': '456'
|
||||
}
|
||||
}
|
||||
diff_content = response.diff_response(resp_obj, expected_resp_json)
|
||||
resp_obj = response.ResponseObject(resp)
|
||||
diff_content = resp_obj.diff_response(expected_resp_json)
|
||||
self.assertFalse(diff_content)
|
||||
|
||||
def test_diff_response_headers_not_equal(self):
|
||||
resp_obj = requests.post(
|
||||
resp = requests.post(
|
||||
url="http://127.0.0.1:5000/customize-response",
|
||||
json={
|
||||
'headers': {
|
||||
@@ -99,7 +104,8 @@ class TestResponse(ApiServerUnittest):
|
||||
'd': 890
|
||||
}
|
||||
}
|
||||
diff_content = response.diff_response(resp_obj, expected_resp_json)
|
||||
resp_obj = response.ResponseObject(resp)
|
||||
diff_content = resp_obj.diff_response(expected_resp_json)
|
||||
self.assertEqual(
|
||||
diff_content['headers'],
|
||||
{
|
||||
@@ -109,7 +115,7 @@ class TestResponse(ApiServerUnittest):
|
||||
)
|
||||
|
||||
def test_diff_response_body_equal(self):
|
||||
resp_obj = requests.post(
|
||||
resp = requests.post(
|
||||
url="http://127.0.0.1:5000/customize-response",
|
||||
json={
|
||||
'body': {
|
||||
@@ -121,7 +127,8 @@ class TestResponse(ApiServerUnittest):
|
||||
|
||||
# expected response body is not specified
|
||||
expected_resp_json = {}
|
||||
diff_content = response.diff_response(resp_obj, expected_resp_json)
|
||||
resp_obj = response.ResponseObject(resp)
|
||||
diff_content = resp_obj.diff_response(expected_resp_json)
|
||||
self.assertFalse(diff_content)
|
||||
|
||||
# response body is the same as expected response body
|
||||
@@ -131,11 +138,12 @@ class TestResponse(ApiServerUnittest):
|
||||
'count': '10'
|
||||
}
|
||||
}
|
||||
diff_content = response.diff_response(resp_obj, expected_resp_json)
|
||||
resp_obj = response.ResponseObject(resp)
|
||||
diff_content = resp_obj.diff_response(expected_resp_json)
|
||||
self.assertFalse(diff_content)
|
||||
|
||||
def test_diff_response_body_not_equal_type_unmatch(self):
|
||||
resp_obj = requests.post(
|
||||
resp = requests.post(
|
||||
url="http://127.0.0.1:5000/customize-response",
|
||||
json={
|
||||
'body': {
|
||||
@@ -149,7 +157,8 @@ class TestResponse(ApiServerUnittest):
|
||||
expected_resp_json = {
|
||||
'body': "ok"
|
||||
}
|
||||
diff_content = response.diff_response(resp_obj, expected_resp_json)
|
||||
resp_obj = response.ResponseObject(resp)
|
||||
diff_content = resp_obj.diff_response(expected_resp_json)
|
||||
self.assertEqual(
|
||||
diff_content['body'],
|
||||
{
|
||||
@@ -159,7 +168,7 @@ class TestResponse(ApiServerUnittest):
|
||||
)
|
||||
|
||||
def test_diff_response_body_not_equal_string_unmatch(self):
|
||||
resp_obj = requests.post(
|
||||
resp = requests.post(
|
||||
url="http://127.0.0.1:5000/customize-response",
|
||||
json={
|
||||
'body': "success"
|
||||
@@ -170,7 +179,8 @@ class TestResponse(ApiServerUnittest):
|
||||
expected_resp_json = {
|
||||
'body': "ok"
|
||||
}
|
||||
diff_content = response.diff_response(resp_obj, expected_resp_json)
|
||||
resp_obj = response.ResponseObject(resp)
|
||||
diff_content = resp_obj.diff_response(expected_resp_json)
|
||||
self.assertEqual(
|
||||
diff_content['body'],
|
||||
{
|
||||
@@ -180,7 +190,7 @@ class TestResponse(ApiServerUnittest):
|
||||
)
|
||||
|
||||
def test_diff_response_body_not_equal_json_unmatch(self):
|
||||
resp_obj = requests.post(
|
||||
resp = requests.post(
|
||||
url="http://127.0.0.1:5000/customize-response",
|
||||
json={
|
||||
'body': {
|
||||
@@ -196,7 +206,8 @@ class TestResponse(ApiServerUnittest):
|
||||
'count': 10
|
||||
}
|
||||
}
|
||||
diff_content = response.diff_response(resp_obj, expected_resp_json)
|
||||
resp_obj = response.ResponseObject(resp)
|
||||
diff_content = resp_obj.diff_response(expected_resp_json)
|
||||
self.assertEqual(
|
||||
diff_content['body'],
|
||||
{
|
||||
@@ -212,7 +223,7 @@ class TestResponse(ApiServerUnittest):
|
||||
)
|
||||
|
||||
def test_extract_response_json(self):
|
||||
resp_obj = requests.post(
|
||||
resp = requests.post(
|
||||
url="http://127.0.0.1:5000/customize-response",
|
||||
json={
|
||||
'headers': {
|
||||
@@ -244,7 +255,8 @@ class TestResponse(ApiServerUnittest):
|
||||
|
||||
test_context = context.Context()
|
||||
test_context.bind_extractors(extract_binds)
|
||||
response.extract_response(resp_obj, test_context)
|
||||
resp_obj = response.ResponseObject(resp)
|
||||
resp_obj.extract_response(test_context)
|
||||
|
||||
extract_binds_dict = test_context.extractors
|
||||
self.assertEqual(
|
||||
@@ -274,7 +286,7 @@ class TestResponse(ApiServerUnittest):
|
||||
|
||||
|
||||
def test_extract_response_fail(self):
|
||||
resp_obj = requests.post(
|
||||
resp = requests.post(
|
||||
url="http://127.0.0.1:5000/customize-response",
|
||||
json={
|
||||
'headers': {
|
||||
@@ -300,9 +312,10 @@ class TestResponse(ApiServerUnittest):
|
||||
|
||||
test_context = context.Context()
|
||||
test_context.bind_extractors(extract_binds)
|
||||
resp_obj = response.ResponseObject(resp)
|
||||
|
||||
with self.assertRaises(exception.ParamsError):
|
||||
response.extract_response(resp_obj, test_context)
|
||||
resp_obj.extract_response(test_context)
|
||||
|
||||
extract_binds = {
|
||||
"resp_content_list_index_error": "content.person.cities.3"
|
||||
@@ -310,12 +323,13 @@ class TestResponse(ApiServerUnittest):
|
||||
|
||||
test_context = context.Context()
|
||||
test_context.bind_extractors(extract_binds)
|
||||
resp_obj = response.ResponseObject(resp)
|
||||
|
||||
with self.assertRaises(exception.ParamsError):
|
||||
response.extract_response(resp_obj, test_context)
|
||||
resp_obj.extract_response(test_context)
|
||||
|
||||
def test_extract_response_json_string(self):
|
||||
resp_obj = requests.post(
|
||||
resp = requests.post(
|
||||
url="http://127.0.0.1:5000/customize-response",
|
||||
json={
|
||||
'headers': {
|
||||
@@ -331,7 +345,8 @@ class TestResponse(ApiServerUnittest):
|
||||
|
||||
test_context = context.Context()
|
||||
test_context.bind_extractors(extract_binds)
|
||||
response.extract_response(resp_obj, test_context)
|
||||
resp_obj = response.ResponseObject(resp)
|
||||
resp_obj.extract_response(test_context)
|
||||
|
||||
extract_binds_dict = test_context.extractors
|
||||
self.assertEqual(
|
||||
|
||||
Reference in New Issue
Block a user