mirror of
https://github.com/httprunner/httprunner.git
synced 2026-05-13 17:29:56 +08:00
feat: log detailed request & response when failed
This commit is contained in:
@@ -4,7 +4,7 @@ import jmespath
|
||||
import requests
|
||||
from loguru import logger
|
||||
|
||||
from httprunner.v3.exceptions import ValidationFailure
|
||||
from httprunner.v3.exceptions import ValidationFailure, ParamsError
|
||||
from httprunner.v3.parser import parse_data, parse_string_value, get_mapping_function
|
||||
from httprunner.v3.schema import VariablesMapping, Validators, FunctionsMapping
|
||||
from httprunner.v3.validator import uniform_validator
|
||||
@@ -19,6 +19,7 @@ class ResponseObject(object):
|
||||
resp_obj (instance): requests.Response instance
|
||||
|
||||
"""
|
||||
self.resp_obj = resp_obj
|
||||
self.resp_obj_meta = {
|
||||
"status_code": resp_obj.status_code,
|
||||
"headers": resp_obj.headers,
|
||||
@@ -26,6 +27,22 @@ class ResponseObject(object):
|
||||
}
|
||||
self.validation_results = {}
|
||||
|
||||
def __getattr__(self, key):
|
||||
try:
|
||||
if key == "json":
|
||||
value = self.resp_obj.json()
|
||||
elif key == "cookies":
|
||||
value = self.resp_obj.cookies.get_dict()
|
||||
else:
|
||||
value = getattr(self.resp_obj, key)
|
||||
|
||||
self.__dict__[key] = value
|
||||
return value
|
||||
except AttributeError:
|
||||
err_msg = f"ResponseObject does not have attribute: {key}"
|
||||
logger.error(err_msg)
|
||||
raise ParamsError(err_msg)
|
||||
|
||||
def extract(self, extractors: Dict[Text, Text]) -> Dict[Text, Any]:
|
||||
if not extractors:
|
||||
return {}
|
||||
@@ -90,13 +107,11 @@ class ResponseObject(object):
|
||||
validate_pass = False
|
||||
validator_dict["check_result"] = "fail"
|
||||
validate_msg += "\t==> fail"
|
||||
validate_msg += "\n{}({}) {} {}({})".format(
|
||||
check_value,
|
||||
type(check_value).__name__,
|
||||
assert_method,
|
||||
expect_value,
|
||||
type(expect_value).__name__
|
||||
)
|
||||
validate_msg += f"\n" \
|
||||
f"check_item: {check_item}\n" \
|
||||
f"check_value: {check_value}({type(check_value).__name__})\n" \
|
||||
f"assert_method: {assert_method}\n" \
|
||||
f"expect_value: {expect_value}({type(expect_value).__name__})"
|
||||
logger.error(validate_msg)
|
||||
failures.append(validate_msg)
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ from typing import List
|
||||
|
||||
from loguru import logger
|
||||
|
||||
from httprunner import utils
|
||||
from httprunner.client import HttpSession
|
||||
from httprunner.v3.exceptions import ValidationFailure
|
||||
from httprunner.v3.parser import build_url, parse_data, parse_variables_mapping
|
||||
@@ -52,6 +53,28 @@ class TestCaseRunner(object):
|
||||
resp = self.session.request(method, url, **parsed_request_dict)
|
||||
resp_obj = ResponseObject(resp)
|
||||
|
||||
def log_req_resp_details():
|
||||
err_msg = "\n{} DETAILED REQUEST & RESPONSE {}\n".format("*" * 32, "*" * 32)
|
||||
|
||||
# log request
|
||||
err_msg += "====== request details ======\n"
|
||||
err_msg += f"url: {url}\n"
|
||||
err_msg += f"method: {method}\n"
|
||||
headers = parsed_request_dict.pop("headers", {})
|
||||
err_msg += f"headers: {headers}\n"
|
||||
for k, v in parsed_request_dict.items():
|
||||
v = utils.omit_long_data(v)
|
||||
err_msg += f"{k}: {repr(v)}\n"
|
||||
|
||||
err_msg += "\n"
|
||||
|
||||
# log response
|
||||
err_msg += "====== response details ======\n"
|
||||
err_msg += f"status_code: {resp_obj.status_code}\n"
|
||||
err_msg += f"headers: {resp_obj.headers}\n"
|
||||
err_msg += f"body: {repr(resp_obj.text)}\n"
|
||||
logger.error(err_msg)
|
||||
|
||||
# extract
|
||||
extractors = step.extract
|
||||
extract_mapping = resp_obj.extract(extractors)
|
||||
@@ -64,6 +87,7 @@ class TestCaseRunner(object):
|
||||
try:
|
||||
resp_obj.validate(validators, variables_mapping, self.config.functions)
|
||||
except ValidationFailure:
|
||||
log_req_resp_details()
|
||||
raise
|
||||
finally:
|
||||
self.validation_results = resp_obj.validation_results
|
||||
|
||||
Reference in New Issue
Block a user