Last active
December 8, 2015 09:26
-
-
Save gfrlv/943886890e9529e986b5 to your computer and use it in GitHub Desktop.
match json error description with hamcrest
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#coding: utf-8 | |
from copy import deepcopy | |
import re | |
from hamcrest.core.base_matcher import BaseMatcher | |
from hamcrest import assert_that | |
from webob import Response | |
# Это хранится в конфиге: | |
error_skeleton = { | |
'code': 'invalid_content_publication', | |
'message': 'cannot publish catalog {catalog_id}:{catalog_revision}', | |
'duplicate': [], | |
'missing': [] | |
} | |
fields_error_skeleton = { | |
"status_code": 400, | |
"code": "invalid_parameter_value", | |
"message": "Invalid parameter value", | |
"errors": [] | |
} | |
# Это приходит от API: | |
error_instance = { | |
"code": "invalid_content_publication", | |
"message": "cannot publish catalog 31fd2d1c-a8df-40c8-8815-9d7129f3b3a1:1", | |
"duplicate": | |
[ | |
"1c034690-45f0-43a0-9670-1f0493bd5c5d" | |
], | |
"missing": [] | |
} | |
fields_error_instance = { | |
"code": "invalid_parameter_value", | |
"message": "Invalid parameter value", | |
"errors": [ | |
{ | |
"field": "id", | |
"type": "invalid", | |
}, | |
{ | |
"field": "msisdn", | |
"type": "missing" | |
} | |
] | |
} | |
# Если параметров нет, ошибка хранится как есть | |
simple_error = { | |
'code': 'error_code', | |
'message': 'Error Message' | |
} | |
class ErrorMatcher(BaseMatcher): | |
def __init__(self, error_skeleton, fields_attr='errors'): | |
self.skeleton = deepcopy(error_skeleton) | |
self.status_code = self.skeleton.pop('status_code') \ | |
if 'status_code' in self.skeleton \ | |
else None | |
self.fields_attr = fields_attr | |
def _match_dict(self, error_dict): | |
if self.fields_attr in error_dict: | |
error_dict[self.fields_attr].sort() | |
return error_dict == self.skeleton | |
def _matches(self, item): | |
if isinstance(item, dict): | |
return self._match_dict(item) | |
else: | |
return self._match_dict(item.json) and item.status_code == self.status_code | |
def describe_to(self, description): | |
return description.append(u'<{}>'.format(self.skeleton)) | |
def with_params(self, **kwargs): | |
for key, val in kwargs.iteritems(): | |
if key in self.skeleton: | |
self.skeleton[key] = val | |
escaped_name = r'\{' + re.escape(key) + '\}' | |
for param_name, param_value in self.skeleton.iteritems(): | |
if not isinstance(param_value, basestring): | |
continue | |
self.skeleton[param_name] = re.sub(escaped_name, unicode(val), param_value) | |
return self | |
def with_fields(self, **kwargs): | |
if not self.fields_attr: | |
return self | |
error_list = [] | |
for error_field, error_type in kwargs.iteritems(): | |
error_list.append( | |
{ | |
'field': error_field, | |
'type': error_type, | |
} | |
) | |
self.skeleton[self.fields_attr] = sorted(error_list) | |
return self | |
def contains_error(item): | |
return ErrorMatcher(item) | |
assert_that( | |
error_instance, | |
contains_error( | |
error_skeleton | |
).with_params( | |
catalog_id='31fd2d1c-a8df-40c8-8815-9d7129f3b3a1', | |
catalog_revision=1, | |
duplicate=['1c034690-45f0-43a0-9670-1f0493bd5c5d']) | |
) | |
assert_that(simple_error, contains_error(simple_error)) | |
assert_that( | |
fields_error_instance, | |
contains_error(fields_error_skeleton).with_fields(id='invalid', msisdn='missing') | |
) | |
assert_that( | |
fields_error_instance, | |
contains_error(fields_error_skeleton).with_fields(msisdn='missing', id='invalid') | |
) | |
fields_error_response = Response(json=fields_error_instance, status='400 Invalid Parameter') | |
assert_that(fields_error_response, | |
contains_error(fields_error_skeleton).with_fields(msisdn='missing', id='invalid')) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment