def _check_status_code(self, status_code, body): expected_code = self.expected["status_code"] if (isinstance(expected_code, int) and status_code == expected_code) or ( isinstance(expected_code, list) and (status_code in expected_code) ): logger.debug( "Status code '%s' matched expected '%s'", status_code, expected_code ) return else: if 400 <= status_code < 500: # special case if there was a bad request. This assumes that the # response would contain some kind of information as to why this # request was rejected. self._adderr( "Status code was %s, expected %s:\n%s", status_code, expected_code, indent_err_text(json.dumps(body)), ) else: self._adderr( "Status code was %s, expected %s", status_code, expected_code )
def _validate_block(self, validate_block): """Validate response """ for validator in validate_block: for key, validator_args in validator.items(): try: formatted_validate_args = format_keys( validator_args, self.test_block_config["variables"]) except Exception as e: # pylint: disable=broad-except self._adderr("Format validate args %s for '%s' faild", validator_args, key, e=e) else: if key == "$ext": validate_fn = get_wrapped_response_function( formatted_validate_args) try: validate_fn(self.response) except Exception as e: # pylint: disable=broad-except self._adderr( "Error calling validate function '%s':\n%s", validate_fn.func, indent_err_text(traceback.format_exc()), e=e) else: try: comparator = comparators.get_comparator(key) except Exception as e: # pylint: disable=broad-except self._adderr( "Error getting comparator function '%s'". format, key, e=e) else: kwargs = {} if len(formatted_validate_args) > 2: kwargs = formatted_validate_args.pop() try: comparator(*formatted_validate_args, **kwargs) except Exception as e: # pylint: disable=broad-except self._adderr( "Error calling comparator function '%s':\n%s", key, indent_err_text(traceback.format_exc()), e=e)
def _save_value(self, save_block): """Save a value in the response for use in future tests Args: to_check (dict): An element of the response from which the given key is extracted key (str): Key to use Returns: dict: dictionary of save_name: value, where save_name is the key we wanted to save this value as """ saved = {} for save_as, joined_key in save_block.items(): try: logger.debug("start format save key:%s", joined_key) val = format_keys(joined_key, self.test_block_config["variables"]) except Exception as e: # pylint: disable=broad-except self._adderr("Format saved value %s for '%s' faild", joined_key, save_as, e=e) else: if save_as == "$ext": ext_fn = get_wrapped_response_function(val) try: to_save = ext_fn(self.response) except Exception as e: # pylint: disable=broad-except self._adderr("Error calling save function '%s':\n%s", ext_fn.func, indent_err_text(traceback.format_exc()), e=e) else: if isinstance(to_save, dict): saved.update(to_save) elif to_save is not None: self._adderr( "Unexpected return value '%s' from $ext save function" ) else: split_keys = save_as.split(".") try: recurse_set_value(saved, split_keys, val) except Exception as e: # pylint: disable=broad-except self._adderr("Set value to '%s' failed", save_as, e=e) return saved
def verify(self, response): """Verify response against expected values and returns any values that we wanted to save for use in future requests There are various ways to 'validate' a block - a specific function, just matching values, validating a schema, etc... Args: response (requests.Response): response object Returns: dict: Any saved values Raises: TestFailError: Something went wrong with validating the response """ self._verbose_log_response(response) self.response = response self.status_code = response.status_code try: body = response.json() except ValueError: body = None self._check_status_code(response.status_code, body) if self.validate_function: try: self.validate_function(response) except Exception as e: # pylint: disable=broad-except self._adderr( "Error calling validate function '%s':\n%s", self.validate_function.func, indent_err_text(traceback.format_exc()), e=e, ) # Get any keys to save saved = {} redirect_query_params = self._get_redirect_query_params(response) saved.update(self._save_value("body", body)) saved.update(self._save_value("headers", response.headers)) saved.update( self._save_value("redirect_query_params", redirect_query_params)) for cookie in self.expected.get("cookies", []): if cookie not in response.cookies: self._adderr("No cookie named '%s' in response", cookie) try: wrapped = get_wrapped_response_function( self.expected["save"]["$ext"]) except KeyError: logger.debug("No save function for this stage") else: try: to_save = wrapped(response) except Exception as e: # pylint: disable=broad-except self._adderr( "Error calling save function '%s':\n%s", wrapped.func, indent_err_text(traceback.format_exc()), e=e, ) else: if isinstance(to_save, dict): saved.update(to_save) elif to_save is not None: self._adderr( "Unexpected return value '%s' from $ext save function") self._validate_block("body", body) self._validate_block("headers", response.headers) self._validate_block("redirect_query_params", redirect_query_params) if self.errors: raise TestFailError( "Test '{:s}' failed:\n{:s}".format(self.name, self._str_errors()), failures=self.errors, ) return saved