diff --git a/gabbi/case.py b/gabbi/case.py index 4f30857..6632421 100644 --- a/gabbi/case.py +++ b/gabbi/case.py @@ -36,6 +36,8 @@ import wsgi_intercept from gabbi import json_parser from gabbi import utils +MAX_CHARS_OUTPUT = 2000 + REPLACERS = [ 'SCHEME', 'NETLOC', @@ -308,11 +310,13 @@ class HTTPTestCase(unittest.TestCase): # Decode and store response decoded_output = utils.decode_content(response, content) - content_type = response.get('content-type', '').lower() + self.content_type = response.get('content-type', '').lower() if (decoded_output and - ('application/json' in content_type or - '+json' in content_type)): + ('application/json' in self.content_type or + '+json' in self.content_type)): self.json_data = json.loads(decoded_output) + else: + self.json_data = None self.output = decoded_output def _run_test(self): @@ -402,7 +406,37 @@ class HTTPTestCase(unittest.TestCase): statii = [stat.strip() for stat in expected_status.split('||')] else: statii = [expected_status.strip()] - self.assertIn(observed_status, statii) + + self.assert_in_or_print_output(observed_status, statii) + + def assert_in_or_print_output(self, expected, iterable): + if utils.not_binary(self.content_type): + if expected in iterable: + return + + if self.json_data: + full_response = json.dumps(self.json_data, indent=2, + separators=(',', ': ')) + else: + full_response = self.output + + max_chars = os.getenv('GABBIT_MAX_CHARS_OUTPUT', MAX_CHARS_OUTPUT) + response = full_response[0:max_chars] + is_truncated = (len(response) != len(full_response)) + + if iterable == self.output: + msg = "'%s' not found in %s%s" % ( + expected, response, + '\n...truncated...' if is_truncated else '' + ) + else: + msg = "'%s' not found in %s, %sresponse:\n%s" % ( + expected, iterable, + 'truncated ' if is_truncated else '', + response) + self.fail(msg) + else: + self.assertIn(expected, iterable) class ServerError(Exception): diff --git a/gabbi/handlers.py b/gabbi/handlers.py index e364c78..a8b42e8 100644 --- a/gabbi/handlers.py +++ b/gabbi/handlers.py @@ -82,7 +82,7 @@ class StringResponseHandler(ResponseHandler): def action(self, test, expected, value=None): expected = test.replace_template(expected) - test.assertIn(expected, test.output) + test.assert_in_or_print_output(expected, test.output) class JSONResponseHandler(ResponseHandler): diff --git a/gabbi/tests/test_handlers.py b/gabbi/tests/test_handlers.py index 18ce8b3..a92d53e 100644 --- a/gabbi/tests/test_handlers.py +++ b/gabbi/tests/test_handlers.py @@ -13,6 +13,7 @@ """Test response handlers. """ +import json import unittest from gabbi import case @@ -35,19 +36,55 @@ class HandlersTest(unittest.TestCase): def test_response_strings(self): handler = handlers.StringResponseHandler(self.test_class) + self.test.content_type = "text/plain" + self.test.json_data = None self.test.test_data = {'response_strings': ['alpha', 'beta']} self.test.output = 'alpha\nbeta\n' self._assert_handler(handler) def test_response_strings_fail(self): handler = handlers.StringResponseHandler(self.test_class) + self.test.content_type = "text/plain" + self.test.json_data = None self.test.test_data = {'response_strings': ['alpha', 'beta']} self.test.output = 'alpha\nbta\n' with self.assertRaises(AssertionError): self._assert_handler(handler) + def test_response_strings_fail_big_output(self): + handler = handlers.StringResponseHandler(self.test_class) + self.test.content_type = "text/plain" + self.test.json_data = None + self.test.test_data = {'response_strings': ['alpha', 'beta']} + self.test.output = 'alpha\nbta\n' * 1000 + with self.assertRaises(AssertionError) as cm: + self._assert_handler(handler) + + msg = str(cm.exception) + self.assertEqual(2036, len(msg)) + + def test_response_strings_fail_big_payload(self): + handler = handlers.StringResponseHandler(self.test_class) + self.test.content_type = "application/json" + self.test.test_data = {'response_strings': ['foobar']} + self.test.json_data = { + 'objects': [{'name': 'cw', + 'location': 'barn'}, + {'name': 'chris', + 'location': 'house'}] * 100 + } + self.test.output = json.dumps(self.test.json_data) + with self.assertRaises(AssertionError) as cm: + self._assert_handler(handler) + + msg = str(cm.exception) + self.assertEqual(2038, len(msg)) + # Check the pprint of the json + self.assertIn(' "location": "house"', msg) + def test_response_json_paths(self): handler = handlers.JSONResponseHandler(self.test_class) + self.test.content_type = "application/json" self.test.test_data = {'response_json_paths': { '$.objects[0].name': 'cow', '$.objects[1].location': 'house', @@ -62,6 +99,7 @@ class HandlersTest(unittest.TestCase): def test_response_json_paths_fail_data(self): handler = handlers.JSONResponseHandler(self.test_class) + self.test.content_type = "application/json" self.test.test_data = {'response_json_paths': { '$.objects[0].name': 'cow', '$.objects[1].location': 'house', @@ -77,6 +115,7 @@ class HandlersTest(unittest.TestCase): def test_response_json_paths_fail_path(self): handler = handlers.JSONResponseHandler(self.test_class) + self.test.content_type = "application/json" self.test.test_data = {'response_json_paths': { '$.objects[1].name': 'cow', }}