From 3a012f012e8924abb4a4e6cea66d5530b48163e6 Mon Sep 17 00:00:00 2001 From: debugtalk Date: Tue, 21 Apr 2020 22:42:14 +0800 Subject: [PATCH] feat: log detailed request & response when failed --- httprunner/v3/response.py | 31 +++++++++++++++++++++++-------- httprunner/v3/runner.py | 24 ++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 8 deletions(-) diff --git a/httprunner/v3/response.py b/httprunner/v3/response.py index 81404b80..ce4dde7c 100644 --- a/httprunner/v3/response.py +++ b/httprunner/v3/response.py @@ -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) diff --git a/httprunner/v3/runner.py b/httprunner/v3/runner.py index 1225e795..2b0be8c9 100644 --- a/httprunner/v3/runner.py +++ b/httprunner/v3/runner.py @@ -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