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
+1 -1
View File
@@ -1,7 +1,7 @@
__title__ = 'HttpRunner' __title__ = 'HttpRunner'
__description__ = 'One-stop solution for HTTP(S) testing.' __description__ = 'One-stop solution for HTTP(S) testing.'
__url__ = 'https://github.com/HttpRunner/HttpRunner' __url__ = 'https://github.com/HttpRunner/HttpRunner'
__version__ = '1.5.3' __version__ = '1.5.4'
__author__ = 'debugtalk' __author__ = 'debugtalk'
__author_email__ = 'mail@debugtalk.com' __author_email__ = 'mail@debugtalk.com'
__license__ = 'MIT' __license__ = 'MIT'
+54 -36
View File
@@ -55,17 +55,20 @@ class HttpSession(requests.Session):
""" initialize meta_data, it will store detail data of request and response """ initialize meta_data, it will store detail data of request and response
""" """
self.meta_data = { self.meta_data = {
"url": "N/A", "request": {
"method": "N/A", "url": "N/A",
"request_time": "N/A", "method": "N/A",
"request_headers": {}, "headers": {},
"request_body": "N/A", "start_timestamp": None
"status_code": "N/A", },
"response_headers": {}, "response": {
"response_body": "N/A", "status_code": "N/A",
"content_size": "N/A", "headers": {},
"response_time_ms": "N/A", "content_size": "N/A",
"elapsed_ms": "N/A" "response_time_ms": "N/A",
"elapsed_ms": "N/A",
"content": None
}
} }
def request(self, method, url, name=None, **kwargs): def request(self, method, url, name=None, **kwargs):
@@ -107,10 +110,17 @@ class HttpSession(requests.Session):
:param cert: (optional) :param cert: (optional)
if String, path to ssl client cert file (.pem). If Tuple, ('cert', 'key') pair. 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 # record original request info
self.meta_data["method"] = method self.meta_data["request"]["method"] = method
self.meta_data["url"] = url self.meta_data["request"]["url"] = url
self.meta_data["request_time"] = time.time() 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 # prepend url with hostname unless it's already an absolute URL
url = self._build_url(url) url = self._build_url(url)
@@ -119,35 +129,43 @@ class HttpSession(requests.Session):
response = self._send_request_safe_mode(method, url, **kwargs) response = self._send_request_safe_mode(method, url, **kwargs)
# record the consumed time # record the consumed time
self.meta_data["response_time_ms"] = round((time.time() - self.meta_data["request_time"]) * 1000, 2) self.meta_data["response"]["response_time_ms"] = \
self.meta_data["elapsed_ms"] = response.elapsed.microseconds / 1000.0 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 # record actual request info
self.meta_data["url"] = (response.history and response.history[0] or response).request.url 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"]["headers"] = response.request.headers
self.meta_data["request_body"] = response.request.body self.meta_data["request"]["body"] = response.request.body
# log request details in debug mode
log_print("request")
# record response info # record response info
self.meta_data["status_code"] = response.status_code self.meta_data["response"]["ok"] = response.ok
self.meta_data["response_headers"] = response.headers self.meta_data["response"]["url"] = response.url
try: self.meta_data["response"]["status_code"] = response.status_code
self.meta_data["response_body"] = response.json() self.meta_data["response"]["reason"] = response.reason
except ValueError: self.meta_data["response"]["headers"] = response.headers
self.meta_data["response_body"] = response.content 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 try:
msg = "response details:\n" self.meta_data["response"]["json"] = response.json()
msg += "> status_code: {}\n".format(self.meta_data["status_code"]) except ValueError:
msg += "> headers: {}\n".format(self.meta_data["response_headers"]) self.meta_data["response"]["json"] = None
msg += "> body: {}".format(self.meta_data["response_body"])
logger.log_debug(msg)
# get the length of the content, but if the argument stream is set to True, we take # 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 # the size from the content-length header, in order to not trigger fetching of the body
if kwargs.get("stream", False): 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: 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: try:
response.raise_for_status() response.raise_for_status()
@@ -156,9 +174,9 @@ class HttpSession(requests.Session):
else: else:
logger.log_info( logger.log_info(
"""status_code: {}, response_time(ms): {} ms, response_length: {} bytes""".format( """status_code: {}, response_time(ms): {} ms, response_length: {} bytes""".format(
self.meta_data["status_code"], self.meta_data["response"]["status_code"],
self.meta_data["response_time_ms"], self.meta_data["response"]["response_time_ms"],
self.meta_data["content_size"] self.meta_data["response"]["content_size"]
) )
) )
+1 -1
View File
@@ -121,7 +121,7 @@ def stringify_body(meta_data, request_or_response):
resp_content_type = headers.get("Content-Type", "") resp_content_type = headers.get("Content-Type", "")
try: try:
if "image" in resp_content_type: if "image" in resp_content_type:
meta_data["response_data_type"] = "image" meta_data["response"]["data_type"] = "image"
body = "data:{};base64,{}".format( body = "data:{};base64,{}".format(
resp_content_type, resp_content_type,
b64encode(body).decode('utf-8') b64encode(body).decode('utf-8')
@@ -236,7 +236,7 @@
<tr id="record_{{record_index}}"> <tr id="record_{{record_index}}">
<th class="{{record.status}}" style="width:5em;">{{record.status}}</td> <th class="{{record.status}}" style="width:5em;">{{record.status}}</td>
<td colspan="2">{{record.name}}</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"> <td class="detail">
<a class="button" href="#popup_log_{{record_index}}">log</a> <a class="button" href="#popup_log_{{record_index}}">log</a>
@@ -249,66 +249,51 @@
<h3>Request:</h3> <h3>Request:</h3>
<div style="overflow: auto"> <div style="overflow: auto">
<table> <table>
<tr> {% for key, value in record.meta_data.request.items() %}
<th>url</th> <tr>
<td>{{ record.meta_data.url }}</td> <th>{{key}}</th>
</tr> <td>
<tr> {% if key == "headers" %}
<th>method</th> {% for header_key, header_value in record.meta_data.request.headers.items() %}
<td>{{ record.meta_data.method }}</td> <div>
</tr> <strong>{{ header_key }}</strong>: {{ header_value }}
<tr> </div>
<th>headers</th> {% endfor %}
<td> {% else %}
{% for key, value in record.meta_data.request_headers.items() %} {{value}}
<div> {% endif %}
<strong>{{ key }}</strong>: {{ value }} </td>
</div> </tr>
{% endfor %} {% 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 %}
</table> </table>
</div> </div>
<h3>Response:</h3> <h3>Response:</h3>
<div style="overflow: auto"> <div style="overflow: auto">
<table> <table>
<tr> {% for key, value in record.meta_data.response.items() %}
<th>status_code</th> <tr>
<td> <th>{{key}}</th>
{{ record.meta_data.status_code }} <td>
</td> {% if key == "headers" %}
</tr> {% for header_key, header_value in record.meta_data.request.headers.items() %}
<tr> <div>
<th>headers</th> <strong>{{ header_key }}</strong>: {{ header_value }}
<td> </div>
{% for key, value in record.meta_data.response_headers.items() %} {% endfor %}
<div> {% elif key == "data_type" %}
<strong>{{ key }}</strong>: {{ value }} {% if value == "image" %}
</div> <img src="{{ record.meta_data.response.body }}" />
{% endfor %} {% else %}
</td> <pre>{{ record.meta_data.response.body }}</pre>
</tr> {% endif %}
<tr> {% else %}
<th>body</th> {{value}}
<td> {% endif %}
{% if record.meta_data.response_data_type == "image" %} </td>
<img src="{{ record.meta_data.response_body }}" /> </tr>
{% else %} {% endfor %}
<pre>{{ record.meta_data.response_body }}</pre> </table>
{% endif %}
</td>
</tr>
</table>
</div> </div>
<h3>Validators:</h3> <h3>Validators:</h3>
@@ -344,15 +329,15 @@
<table> <table>
<tr> <tr>
<th>content_size(bytes)</th> <th>content_size(bytes)</th>
<td>{{ record.meta_data.content_size }}</td> <td>{{ record.meta_data.response.content_size }}</td>
</tr> </tr>
<tr> <tr>
<th>response_time(ms)</th> <th>response_time(ms)</th>
<td>{{ record.meta_data.response_time_ms }}</td> <td>{{ record.meta_data.response.response_time_ms }}</td>
</tr> </tr>
<tr> <tr>
<th>elapsed(ms)</th> <th>elapsed(ms)</th>
<td>{{ record.meta_data.elapsed_ms }}</td> <td>{{ record.meta_data.response.elapsed_ms }}</td>
</tr> </tr>
</table> </table>
</div> </div>
+1 -1
View File
@@ -137,7 +137,7 @@ class TestHttpRunner(ApiServerUnittest):
summary = runner.summary summary = runner.summary
self.assertTrue(summary["success"]) self.assertTrue(summary["success"])
self.assertEqual(summary["stat"]["testsRun"], 1) 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): def test_html_report_repsonse_image(self):
testset_path = "tests/httpbin/load_image.yml" testset_path = "tests/httpbin/load_image.yml"