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