record more info about request and response, and display in report

This commit is contained in:
debugtalk
2018-07-21 11:40:44 +08:00
parent b48dbc27b8
commit c7af7b3934
5 changed files with 100 additions and 97 deletions

View File

@@ -1,7 +1,7 @@
__title__ = 'HttpRunner'
__description__ = 'One-stop solution for HTTP(S) testing.'
__url__ = 'https://github.com/HttpRunner/HttpRunner'
__version__ = '1.5.3'
__version__ = '1.5.4'
__author__ = 'debugtalk'
__author_email__ = 'mail@debugtalk.com'
__license__ = 'MIT'

View File

@@ -55,17 +55,20 @@ class HttpSession(requests.Session):
""" initialize meta_data, it will store detail data of request and response
"""
self.meta_data = {
"url": "N/A",
"method": "N/A",
"request_time": "N/A",
"request_headers": {},
"request_body": "N/A",
"status_code": "N/A",
"response_headers": {},
"response_body": "N/A",
"content_size": "N/A",
"response_time_ms": "N/A",
"elapsed_ms": "N/A"
"request": {
"url": "N/A",
"method": "N/A",
"headers": {},
"start_timestamp": None
},
"response": {
"status_code": "N/A",
"headers": {},
"content_size": "N/A",
"response_time_ms": "N/A",
"elapsed_ms": "N/A",
"content": None
}
}
def request(self, method, url, name=None, **kwargs):
@@ -107,10 +110,17 @@ class HttpSession(requests.Session):
:param cert: (optional)
if String, path to ssl client cert file (.pem). If Tuple, ('cert', 'key') pair.
"""
def log_print(request_response):
msg = "\n================== {} details ==================\n".format(request_response)
for key, value in self.meta_data[request_response].items():
msg += "{:<16} : {}\n".format(key, value)
logger.log_debug(msg)
# record original request info
self.meta_data["method"] = method
self.meta_data["url"] = url
self.meta_data["request_time"] = time.time()
self.meta_data["request"]["method"] = method
self.meta_data["request"]["url"] = url
self.meta_data["request"].update(kwargs)
self.meta_data["request"]["start_timestamp"] = time.time()
# prepend url with hostname unless it's already an absolute URL
url = self._build_url(url)
@@ -119,35 +129,43 @@ class HttpSession(requests.Session):
response = self._send_request_safe_mode(method, url, **kwargs)
# record the consumed time
self.meta_data["response_time_ms"] = round((time.time() - self.meta_data["request_time"]) * 1000, 2)
self.meta_data["elapsed_ms"] = response.elapsed.microseconds / 1000.0
self.meta_data["response"]["response_time_ms"] = \
round((time.time() - self.meta_data["request"]["start_timestamp"]) * 1000, 2)
self.meta_data["response"]["elapsed_ms"] = response.elapsed.microseconds / 1000.0
# record actual request info
self.meta_data["url"] = (response.history and response.history[0] or response).request.url
self.meta_data["request_headers"] = response.request.headers
self.meta_data["request_body"] = response.request.body
self.meta_data["request"]["url"] = (response.history and response.history[0] or response).request.url
self.meta_data["request"]["headers"] = response.request.headers
self.meta_data["request"]["body"] = response.request.body
# log request details in debug mode
log_print("request")
# record response info
self.meta_data["status_code"] = response.status_code
self.meta_data["response_headers"] = response.headers
try:
self.meta_data["response_body"] = response.json()
except ValueError:
self.meta_data["response_body"] = response.content
self.meta_data["response"]["ok"] = response.ok
self.meta_data["response"]["url"] = response.url
self.meta_data["response"]["status_code"] = response.status_code
self.meta_data["response"]["reason"] = response.reason
self.meta_data["response"]["headers"] = response.headers
self.meta_data["response"]["cookies"] = response.cookies or {}
self.meta_data["response"]["encoding"] = response.encoding
self.meta_data["response"]["content"] = response.content
self.meta_data["response"]["text"] = response.text
# log response details in debug mode
msg = "response details:\n"
msg += "> status_code: {}\n".format(self.meta_data["status_code"])
msg += "> headers: {}\n".format(self.meta_data["response_headers"])
msg += "> body: {}".format(self.meta_data["response_body"])
logger.log_debug(msg)
try:
self.meta_data["response"]["json"] = response.json()
except ValueError:
self.meta_data["response"]["json"] = None
# get the length of the content, but if the argument stream is set to True, we take
# the size from the content-length header, in order to not trigger fetching of the body
if kwargs.get("stream", False):
self.meta_data["content_size"] = int(self.meta_data["response_headers"].get("content-length") or 0)
self.meta_data["response"]["content_size"] = int(self.meta_data["response"]["headers"].get("content-length") or 0)
else:
self.meta_data["content_size"] = len(response.content or "")
self.meta_data["response"]["content_size"] = len(response.content or "")
# log response details in debug mode
log_print("response")
try:
response.raise_for_status()
@@ -156,9 +174,9 @@ class HttpSession(requests.Session):
else:
logger.log_info(
"""status_code: {}, response_time(ms): {} ms, response_length: {} bytes""".format(
self.meta_data["status_code"],
self.meta_data["response_time_ms"],
self.meta_data["content_size"]
self.meta_data["response"]["status_code"],
self.meta_data["response"]["response_time_ms"],
self.meta_data["response"]["content_size"]
)
)

View File

@@ -121,7 +121,7 @@ def stringify_body(meta_data, request_or_response):
resp_content_type = headers.get("Content-Type", "")
try:
if "image" in resp_content_type:
meta_data["response_data_type"] = "image"
meta_data["response"]["data_type"] = "image"
body = "data:{};base64,{}".format(
resp_content_type,
b64encode(body).decode('utf-8')

View File

@@ -236,7 +236,7 @@
<tr id="record_{{record_index}}">
<th class="{{record.status}}" style="width:5em;">{{record.status}}</td>
<td colspan="2">{{record.name}}</td>
<td style="text-align:center;width:6em;">{{ record.meta_data.response_time_ms }} ms</td>
<td style="text-align:center;width:6em;">{{ record.meta_data.response.response_time_ms }} ms</td>
<td class="detail">
<a class="button" href="#popup_log_{{record_index}}">log</a>
@@ -249,66 +249,51 @@
<h3>Request:</h3>
<div style="overflow: auto">
<table>
<tr>
<th>url</th>
<td>{{ record.meta_data.url }}</td>
</tr>
<tr>
<th>method</th>
<td>{{ record.meta_data.method }}</td>
</tr>
<tr>
<th>headers</th>
<td>
{% for key, value in record.meta_data.request_headers.items() %}
<div>
<strong>{{ key }}</strong>: {{ value }}
</div>
{% endfor %}
</td>
</tr>
{% if record.meta_data.method in ["POST", "PUT"] %}
<tr>
<th>body</th>
<td>
<pre>{{ record.meta_data.request_body }}</pre>
</td>
</tr>
{% endif %}
{% for key, value in record.meta_data.request.items() %}
<tr>
<th>{{key}}</th>
<td>
{% if key == "headers" %}
{% for header_key, header_value in record.meta_data.request.headers.items() %}
<div>
<strong>{{ header_key }}</strong>: {{ header_value }}
</div>
{% endfor %}
{% else %}
{{value}}
{% endif %}
</td>
</tr>
{% endfor %}
</table>
</div>
<h3>Response:</h3>
<div style="overflow: auto">
<table>
<tr>
<th>status_code</th>
<td>
{{ record.meta_data.status_code }}
</td>
</tr>
<tr>
<th>headers</th>
<td>
{% for key, value in record.meta_data.response_headers.items() %}
<div>
<strong>{{ key }}</strong>: {{ value }}
</div>
{% endfor %}
</td>
</tr>
<tr>
<th>body</th>
<td>
{% if record.meta_data.response_data_type == "image" %}
<img src="{{ record.meta_data.response_body }}" />
{% else %}
<pre>{{ record.meta_data.response_body }}</pre>
{% endif %}
</td>
</tr>
</table>
{% for key, value in record.meta_data.response.items() %}
<tr>
<th>{{key}}</th>
<td>
{% if key == "headers" %}
{% for header_key, header_value in record.meta_data.request.headers.items() %}
<div>
<strong>{{ header_key }}</strong>: {{ header_value }}
</div>
{% endfor %}
{% elif key == "data_type" %}
{% if value == "image" %}
<img src="{{ record.meta_data.response.body }}" />
{% else %}
<pre>{{ record.meta_data.response.body }}</pre>
{% endif %}
{% else %}
{{value}}
{% endif %}
</td>
</tr>
{% endfor %}
</table>
</div>
<h3>Validators:</h3>
@@ -344,15 +329,15 @@
<table>
<tr>
<th>content_size(bytes)</th>
<td>{{ record.meta_data.content_size }}</td>
<td>{{ record.meta_data.response.content_size }}</td>
</tr>
<tr>
<th>response_time(ms)</th>
<td>{{ record.meta_data.response_time_ms }}</td>
<td>{{ record.meta_data.response.response_time_ms }}</td>
</tr>
<tr>
<th>elapsed(ms)</th>
<td>{{ record.meta_data.elapsed_ms }}</td>
<td>{{ record.meta_data.response.elapsed_ms }}</td>
</tr>
</table>
</div>

View File

@@ -137,7 +137,7 @@ class TestHttpRunner(ApiServerUnittest):
summary = runner.summary
self.assertTrue(summary["success"])
self.assertEqual(summary["stat"]["testsRun"], 1)
self.assertEqual(summary["details"][0]["records"][0]["meta_data"]["response_body"]["data"], "abc")
self.assertEqual(summary["details"][0]["records"][0]["meta_data"]["response"]["json"]["data"], "abc")
def test_html_report_repsonse_image(self):
testset_path = "tests/httpbin/load_image.yml"