mirror of
https://github.com/httprunner/httprunner.git
synced 2026-05-12 02:21:29 +08:00
182 lines
5.4 KiB
Python
182 lines
5.4 KiB
Python
import json
|
|
from base64 import b64encode
|
|
from collections import Iterable
|
|
from typing import List
|
|
|
|
from jinja2 import escape
|
|
from requests.cookies import RequestsCookieJar
|
|
|
|
from httprunner.v3.schema import TestSuiteSummary, MetaData
|
|
|
|
|
|
def dumps_json(value):
|
|
""" dumps json value to indented string
|
|
|
|
Args:
|
|
value (dict): raw json data
|
|
|
|
Returns:
|
|
str: indented json dump string
|
|
|
|
"""
|
|
return json.dumps(value, indent=2, ensure_ascii=False)
|
|
|
|
|
|
def detect_encoding(value):
|
|
try:
|
|
return json.detect_encoding(value)
|
|
except AttributeError:
|
|
return "utf-8"
|
|
|
|
|
|
def __stringify_request(request_data):
|
|
""" stringfy HTTP request data
|
|
|
|
Args:
|
|
request_data (dict): HTTP request data in dict.
|
|
|
|
{
|
|
"url": "http://127.0.0.1:5000/api/get-token",
|
|
"method": "POST",
|
|
"headers": {
|
|
"User-Agent": "python-requests/2.20.0",
|
|
"Accept-Encoding": "gzip, deflate",
|
|
"Accept": "*/*",
|
|
"Connection": "keep-alive",
|
|
"user_agent": "iOS/10.3",
|
|
"device_sn": "TESTCASE_CREATE_XXX",
|
|
"os_platform": "ios",
|
|
"app_version": "2.8.6",
|
|
"Content-Type": "application/json",
|
|
"Content-Length": "52"
|
|
},
|
|
"body": b'{"sign": "cb9d60acd09080ea66c8e63a1c78c6459ea00168"}',
|
|
"verify": false
|
|
}
|
|
|
|
"""
|
|
for key, value in request_data.items():
|
|
|
|
if isinstance(value, (list, dict)):
|
|
value = dumps_json(value)
|
|
|
|
elif isinstance(value, bytes):
|
|
try:
|
|
encoding = detect_encoding(value)
|
|
value = value.decode(encoding)
|
|
if key == "body":
|
|
try:
|
|
# request body is in json format
|
|
value = json.loads(value)
|
|
value = dumps_json(value)
|
|
except json.JSONDecodeError:
|
|
pass
|
|
value = escape(value)
|
|
except UnicodeDecodeError:
|
|
pass
|
|
|
|
elif not isinstance(value, (str, bytes, int, float, Iterable)):
|
|
# class instance, e.g. MultipartEncoder()
|
|
value = repr(value)
|
|
|
|
elif isinstance(value, RequestsCookieJar):
|
|
value = value.get_dict()
|
|
|
|
request_data[key] = value
|
|
|
|
|
|
def __stringify_response(response_data):
|
|
""" stringfy HTTP response data
|
|
|
|
Args:
|
|
response_data (dict):
|
|
|
|
{
|
|
"status_code": 404,
|
|
"headers": {
|
|
"Content-Type": "application/json",
|
|
"Content-Length": "30",
|
|
"Server": "Werkzeug/0.14.1 Python/3.7.0",
|
|
"Date": "Tue, 27 Nov 2018 06:19:27 GMT"
|
|
},
|
|
"encoding": "None",
|
|
"content_type": "application/json",
|
|
"ok": false,
|
|
"url": "http://127.0.0.1:5000/api/users/9001",
|
|
"reason": "NOT FOUND",
|
|
"cookies": {},
|
|
"body": {
|
|
"success": false,
|
|
"data": {}
|
|
}
|
|
}
|
|
|
|
"""
|
|
for key, value in response_data.items():
|
|
|
|
if isinstance(value, (list, dict)):
|
|
value = dumps_json(value)
|
|
|
|
elif isinstance(value, bytes):
|
|
try:
|
|
encoding = response_data.get("encoding")
|
|
if not encoding or encoding == "None":
|
|
encoding = detect_encoding(value)
|
|
|
|
if key == "body" and "image" in response_data["content_type"]:
|
|
# display image
|
|
value = "data:{};base64,{}".format(
|
|
response_data["content_type"],
|
|
b64encode(value).decode(encoding)
|
|
)
|
|
else:
|
|
value = escape(value.decode(encoding))
|
|
except UnicodeDecodeError:
|
|
pass
|
|
|
|
elif not isinstance(value, (str, bytes, int, float, Iterable)):
|
|
# class instance, e.g. MultipartEncoder()
|
|
value = repr(value)
|
|
|
|
elif isinstance(value, RequestsCookieJar):
|
|
value = value.get_dict()
|
|
|
|
response_data[key] = value
|
|
|
|
|
|
def __get_total_response_time(step_datas: List[MetaData]):
|
|
""" caculate total response time of all step_datas
|
|
"""
|
|
try:
|
|
response_time = 0
|
|
for step_data in step_datas:
|
|
response_time += step_data.stat.response_time_ms
|
|
|
|
return "{:.2f}".format(response_time)
|
|
|
|
except TypeError:
|
|
# failure exists
|
|
return "N/A"
|
|
|
|
|
|
def __stringify_meta_datas(step_datas: List[MetaData]):
|
|
|
|
for step_data in step_datas:
|
|
data_list = step_data.data
|
|
for data in data_list:
|
|
__stringify_request(data["request"])
|
|
__stringify_response(data["response"])
|
|
|
|
|
|
def stringify_summary(testsuite_summary: TestSuiteSummary):
|
|
""" stringify summary, in order to dump json file and generate html report.
|
|
"""
|
|
for index, testcase_summary in enumerate(testsuite_summary.details):
|
|
|
|
if not testcase_summary.name:
|
|
testcase_summary.name = f"testcase {index}"
|
|
|
|
step_datas = testcase_summary.step_datas
|
|
__stringify_meta_datas(step_datas)
|
|
testcase_summary.total_response_time = __get_total_response_time(step_datas)
|