-
Notifications
You must be signed in to change notification settings - Fork 34
Commit
* Functions moved to utils module * http request moved to own method * redundant data assignment of response and output rationalized
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,6 +30,7 @@ | |
from six.moves.urllib import parse as urlparse | ||
from testtools import testcase | ||
|
||
from gabbi import utils | ||
|
||
REPLACERS = [ | ||
'SCHEME', | ||
|
@@ -125,9 +126,12 @@ def replace_template(self, message): | |
|
||
return message | ||
|
||
def _assert_response(self, response, test): | ||
def _assert_response(self): | ||
"""Compare the response with expected data.""" | ||
|
||
test = self.test_data | ||
response = self.response | ||
|
||
# Never accept a 500 | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
cdent
Author
Owner
|
||
if response['status'] == '500': | ||
raise ServerError(self.output) | ||
|
@@ -244,6 +248,28 @@ def _response_replace(self, message): | |
return re.sub(r"\$RESPONSE\['([^']+)'\]", | ||
self._json_replacer, message) | ||
|
||
def _run_request(self, url, method, headers, body): | ||
"""Run the http request and decode output.""" | ||
|
||
response, content = self.http.request( | ||
url, | ||
method=method, | ||
headers=headers, | ||
body=body | ||
) | ||
|
||
# Set headers and location attributes for follow on requests | ||
self.response = response | ||
if 'location' in response: | ||
self.location = response['location'] | ||
|
||
# Decode and store response | ||
decoded_output = utils.decode_content(response, content) | ||
if (decoded_output and | ||
'application/json' in response.get('content-type', '')): | ||
self.json_data = json.loads(decoded_output) | ||
self.output = decoded_output | ||
|
||
def _run_test(self): | ||
"""Make an HTTP request and compare the response with expectations.""" | ||
test = self.test_data | ||
|
@@ -267,27 +293,8 @@ def _run_test(self): | |
if test['redirects']: | ||
self.http.follow_redirects = True | ||
|
||
# Make the actual request. | ||
response, content = self.http.request( | ||
full_url, | ||
method=method, | ||
headers=headers, | ||
body=body | ||
) | ||
|
||
# Set headers and location attributes for follow on requests | ||
self.response = response | ||
if 'location' in response: | ||
self.location = response['location'] | ||
|
||
# Decode and store response before anything else | ||
decoded_output = _decode_content(response, content) | ||
if (decoded_output and | ||
'application/json' in response.get('content-type', '')): | ||
self.json_data = json.loads(decoded_output) | ||
self.output = decoded_output | ||
|
||
self._assert_response(response, test) | ||
self._run_request(full_url, method, headers, body) | ||
self._assert_response() | ||
|
||
def _scheme_replace(self, message): | ||
"""Replace $SCHEME with the current protocol.""" | ||
|
@@ -301,7 +308,7 @@ def _test_data_to_string(self, data, content_type): | |
if isinstance(data, str): | ||
if data.startswith('<@'): | ||
info = self._load_data_file(data.replace('<@', '', 1)) | ||
if _not_binary(content_type): | ||
if utils.not_binary(content_type): | ||
try: | ||
info = str(info, 'UTF-8') | ||
except TypeError: | ||
|
@@ -354,32 +361,6 @@ def _test_status(self, expected_status, observed_status): | |
self.assertIn(observed_status, statii) | ||
|
||
|
||
def _decode_content(response, content): | ||
"""Decode content to a proper string.""" | ||
content_type = response.get('content-type', | ||
'application/binary').lower() | ||
if ';' in content_type: | ||
content_type, charset = (attr.strip() for attr in | ||
content_type.split(';')) | ||
charset = charset.split('=')[1].strip() | ||
else: | ||
charset = 'utf-8' | ||
|
||
if _not_binary(content_type): | ||
return content.decode(charset) | ||
else: | ||
return content | ||
|
||
|
||
def _not_binary(content_type): | ||
"""Decide if something is content we'd like to treat as a string.""" | ||
return (content_type.startswith('text/') or | ||
content_type.endswith('+xml') or | ||
content_type.endswith('+json') or | ||
content_type == 'application/javascript' or | ||
content_type == 'application/json') | ||
|
||
|
||
class ServerError(Exception): | ||
"""A catchall ServerError.""" | ||
pass |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
# Copyright 2014, 2015 Red Hat | ||
# | ||
# Authors: Chris Dent <chdent@redhat.com> | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); you may | ||
# not use this file except in compliance with the License. You may obtain | ||
# a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
# License for the specific language governing permissions and limitations | ||
# under the License. | ||
"""Utility functions grab bag.""" | ||
|
||
|
||
def decode_content(response, content): | ||
"""Decode content to a proper string.""" | ||
content_type = response.get('content-type', | ||
'application/binary').lower() | ||
if ';' in content_type: | ||
content_type, charset = (attr.strip() for attr in | ||
content_type.split(';')) | ||
charset = charset.split('=')[1].strip() | ||
else: | ||
charset = 'utf-8' | ||
|
||
if not_binary(content_type): | ||
return content.decode(charset) | ||
else: | ||
return content | ||
|
||
|
||
def not_binary(content_type): | ||
"""Decide if something is content we'd like to treat as a string.""" | ||
return (content_type.startswith('text/') or | ||
content_type.endswith('+xml') or | ||
content_type.endswith('+json') or | ||
content_type == 'application/javascript' or | ||
content_type == 'application/json') |
I understand the intent here, but it seems like unnecessary special-casing: Do we really want to prohibit users from explicitly expecting a 500? After all, such an expectation might be temporary, e.g. as part of TDD or while cleaning up an existing implementation.