Merge pull request #214 from cdent/cd/simple-coerce
Manage numerals more effectively in replacers
This commit is contained in:
commit
e18a889245
|
@ -154,6 +154,9 @@ class HTTPTestCase(testtools.TestCase):
|
|||
message[k] = self.replace_template(message[k])
|
||||
return message
|
||||
|
||||
if isinstance(message, list):
|
||||
return [self.replace_template(line) for line in message]
|
||||
|
||||
for replacer in REPLACERS:
|
||||
template = '$%s' % replacer
|
||||
method = '_%s_replace' % replacer.lower()
|
||||
|
@ -187,13 +190,27 @@ class HTTPTestCase(testtools.TestCase):
|
|||
return value
|
||||
|
||||
def _environ_replace(self, message):
|
||||
"""Replace an indicator in a message with the environment value."""
|
||||
"""Replace an indicator in a message with the environment value.
|
||||
|
||||
If value can be a number, cast it as such. If value is a form of
|
||||
"null", "true", or "false" cast it to None, True, False.
|
||||
"""
|
||||
value = re.sub(self._replacer_regex('ENVIRON'),
|
||||
self._environ_replacer, message)
|
||||
if value == "False":
|
||||
try:
|
||||
if '.' in value:
|
||||
value = float(value)
|
||||
else:
|
||||
value = int(value)
|
||||
return value
|
||||
except ValueError:
|
||||
pass
|
||||
if value.lower() == "false":
|
||||
return False
|
||||
if value == "True":
|
||||
if value.lower() == "true":
|
||||
return True
|
||||
if value.lower() == "null":
|
||||
return None
|
||||
return value
|
||||
|
||||
@staticmethod
|
||||
|
@ -351,11 +368,18 @@ class HTTPTestCase(testtools.TestCase):
|
|||
return r"%s\$%s" % (case, key)
|
||||
|
||||
def _response_replace(self, message):
|
||||
"""Replace a content path with the value from a previous response."""
|
||||
return re.sub(self._replacer_regex('RESPONSE'),
|
||||
self._response_replacer, message)
|
||||
"""Replace a content path with the value from a previous response.
|
||||
|
||||
def _response_replacer(self, match):
|
||||
If the match would replace the entire message, then don't cast it
|
||||
to a string.
|
||||
"""
|
||||
regex = self._replacer_regex('RESPONSE')
|
||||
match = re.match('^%s$' % regex, message)
|
||||
if match:
|
||||
return self._response_replacer(match, preserve=True)
|
||||
return re.sub(regex, self._response_replacer, message)
|
||||
|
||||
def _response_replacer(self, match, preserve=False):
|
||||
"""Replace a regex match with the value from a previous response."""
|
||||
response_path = match.group('arg')
|
||||
case = match.group('case')
|
||||
|
@ -368,8 +392,12 @@ class HTTPTestCase(testtools.TestCase):
|
|||
# If no handler can be found use the null replacer,
|
||||
# which returns "foo" when "$RESPONSE['foo']".
|
||||
replacer_class = replacer_class or base.ContentHandler
|
||||
return replacer_class.replacer(
|
||||
result = replacer_class.replacer(
|
||||
referred_case.response_data, response_path)
|
||||
if preserve:
|
||||
return result
|
||||
else:
|
||||
return six.text_type(result)
|
||||
|
||||
def _run_request(self, url, method, headers, body, redirect=False):
|
||||
"""Run the http request and decode output.
|
||||
|
@ -485,6 +513,7 @@ class HTTPTestCase(testtools.TestCase):
|
|||
else:
|
||||
dumper_class = self.get_content_handler(content_type)
|
||||
if dumper_class:
|
||||
data = self.replace_template(data)
|
||||
data = dumper_class.dumps(data, test=self)
|
||||
else:
|
||||
raise ValueError(
|
||||
|
|
|
@ -41,7 +41,7 @@ class JSONHandler(base.ContentHandler):
|
|||
|
||||
@classmethod
|
||||
def replacer(cls, response_data, match):
|
||||
return str(cls.extract_json_path_value(response_data, match))
|
||||
return cls.extract_json_path_value(response_data, match)
|
||||
|
||||
@staticmethod
|
||||
def dumps(data, pretty=False, test=None):
|
||||
|
|
|
@ -0,0 +1,201 @@
|
|||
defaults:
|
||||
request_headers:
|
||||
content-type: application/json
|
||||
verbose: True
|
||||
|
||||
tests:
|
||||
- name: post data
|
||||
POST: /
|
||||
data:
|
||||
one_string: "1"
|
||||
one_int: 1
|
||||
one_float: 1.1
|
||||
response_json_paths:
|
||||
$.one_string: "1"
|
||||
$.one_int: 1
|
||||
$.one_float: 1.1
|
||||
response_strings:
|
||||
- '"one_string": "1"'
|
||||
- '"one_int": 1'
|
||||
- '"one_float": 1.1'
|
||||
|
||||
- name: use data
|
||||
desc: data will be coerced because templates in use
|
||||
POST: /
|
||||
data:
|
||||
one_string: !!str "$RESPONSE['$.one_string']"
|
||||
one_int: $RESPONSE['$.one_int']
|
||||
one_float: $RESPONSE['$.one_float']
|
||||
response_json_paths:
|
||||
$.one_string: "1"
|
||||
$.one_int: 1
|
||||
$.one_float: 1.1
|
||||
response_strings:
|
||||
- '"one_string": "1"'
|
||||
- '"one_int": 1'
|
||||
- '"one_float": 1.1'
|
||||
|
||||
- name: from environ
|
||||
POST: /
|
||||
data:
|
||||
one_environ: $ENVIRON['ONE']
|
||||
response_json_paths:
|
||||
$.one_environ: 1
|
||||
response_strings:
|
||||
- '"one_environ": 1'
|
||||
|
||||
- name: with list
|
||||
POST: /
|
||||
data:
|
||||
- $ENVIRON['ONE']
|
||||
- 2
|
||||
- "3"
|
||||
response_json_paths:
|
||||
$[0]: 1
|
||||
$[1]: 2
|
||||
$[2]: "3"
|
||||
response_strings:
|
||||
- '[1, 2, "3"]'
|
||||
|
||||
- name: object with list
|
||||
desc: without recursive handling no coersion
|
||||
POST: /
|
||||
data:
|
||||
collection:
|
||||
- alpha: $ENVIRON['ONE']
|
||||
beta: max
|
||||
- alpha: 2
|
||||
beta: climb
|
||||
response_json_paths:
|
||||
$.collection[0].alpha: 1
|
||||
$.collection[0].beta: max
|
||||
$.collection[1].alpha: 2
|
||||
$.collection[1].beta: climb
|
||||
response_strings:
|
||||
- '"alpha": 1'
|
||||
- '"beta": "max"'
|
||||
|
||||
- name: post extra data
|
||||
POST: /
|
||||
data:
|
||||
a: 1
|
||||
b: 1.0
|
||||
c: '[1,2,3]'
|
||||
d: true
|
||||
e: false
|
||||
f:
|
||||
key: val
|
||||
g: null
|
||||
h:
|
||||
key:
|
||||
less_key: [1, true, null]
|
||||
more_key: 1
|
||||
response_json_paths:
|
||||
a: 1
|
||||
b: 1.0
|
||||
c: '[1,2,3]'
|
||||
d: true
|
||||
e: false
|
||||
f:
|
||||
key: val
|
||||
g: null
|
||||
h:
|
||||
key:
|
||||
less_key: [1, true, null]
|
||||
more_key: 1
|
||||
|
||||
- name: check posted data
|
||||
POST: /
|
||||
data:
|
||||
a: $RESPONSE['$.a']
|
||||
b: $RESPONSE['$.b']
|
||||
c: $RESPONSE['$.c']
|
||||
d: $RESPONSE['$.d']
|
||||
e: $RESPONSE['$.e']
|
||||
f: $RESPONSE['$.f']
|
||||
g: $RESPONSE['$.g']
|
||||
h: $RESPONSE['$.h']
|
||||
response_json_paths:
|
||||
a: 1
|
||||
b: 1.0
|
||||
c: '[1,2,3]'
|
||||
d: true
|
||||
e: false
|
||||
f:
|
||||
key: val
|
||||
g: null
|
||||
h:
|
||||
key:
|
||||
less_key: [1, true, null]
|
||||
more_key: 1
|
||||
|
||||
- name: Post again and check the results
|
||||
POST: /
|
||||
data:
|
||||
a: $HISTORY['post extra data'].$RESPONSE['$.a']
|
||||
b: $HISTORY['post extra data'].$RESPONSE['$.b']
|
||||
c: $HISTORY['post extra data'].$RESPONSE['$.c']
|
||||
d: $HISTORY['post extra data'].$RESPONSE['$.d']
|
||||
e: $HISTORY['post extra data'].$RESPONSE['$.e']
|
||||
f: $HISTORY['post extra data'].$RESPONSE['$.f']
|
||||
g: $HISTORY['post extra data'].$RESPONSE['$.g']
|
||||
h: $HISTORY['post extra data'].$RESPONSE['$.h']
|
||||
response_json_paths:
|
||||
a: $ENVIRON['ONE']
|
||||
b: $ENVIRON['DECIMAL']
|
||||
c: $ENVIRON['ARRAY_STRING']
|
||||
d: $ENVIRON['TRUE']
|
||||
e: $ENVIRON['FALSE']
|
||||
f:
|
||||
key: $ENVIRON['STRING']
|
||||
g: $ENVIRON['NULL']
|
||||
h:
|
||||
key:
|
||||
less_key:
|
||||
- $ENVIRON['ONE']
|
||||
- $ENVIRON['TRUE']
|
||||
- $ENVIRON['NULL']
|
||||
more_key: $ENVIRON['ONE']
|
||||
|
||||
- name: Post again and check the results (reversed)
|
||||
POST: /
|
||||
data:
|
||||
a: $ENVIRON['ONE']
|
||||
b: $ENVIRON['DECIMAL']
|
||||
c: $ENVIRON['ARRAY_STRING']
|
||||
d: $ENVIRON['TRUE']
|
||||
e: $ENVIRON['FALSE']
|
||||
f:
|
||||
key: $ENVIRON['STRING']
|
||||
g: $ENVIRON['NULL']
|
||||
h:
|
||||
key:
|
||||
less_key:
|
||||
- $ENVIRON['ONE']
|
||||
- $ENVIRON['TRUE']
|
||||
- $ENVIRON['NULL']
|
||||
more_key: $ENVIRON['ONE']
|
||||
response_json_paths:
|
||||
a: $HISTORY['check posted data'].$RESPONSE['$.a']
|
||||
b: $HISTORY['check posted data'].$RESPONSE['$.b']
|
||||
c: $HISTORY['check posted data'].$RESPONSE['$.c']
|
||||
d: $HISTORY['check posted data'].$RESPONSE['$.d']
|
||||
e: $HISTORY['check posted data'].$RESPONSE['$.e']
|
||||
f: $HISTORY['check posted data'].$RESPONSE['$.f']
|
||||
g: $HISTORY['check posted data'].$RESPONSE['$.g']
|
||||
h:
|
||||
key:
|
||||
less_key:
|
||||
- $HISTORY['check posted data'].$RESPONSE['$.h.key.less_key[0]']
|
||||
- $HISTORY['check posted data'].$RESPONSE['$.h.key.less_key[1]']
|
||||
- $HISTORY['check posted data'].$RESPONSE['$.h.key.less_key[2]']
|
||||
more_key: $HISTORY['check posted data'].$RESPONSE['$.h.key.more_key']
|
||||
|
||||
- name: string internal replace
|
||||
POST: /
|
||||
data:
|
||||
endpoint_resp: /api/0.1/item/$HISTORY['check posted data'].$RESPONSE['$.a']
|
||||
endpoint_var: /api/0.1/item/$ENVIRON['ONE']
|
||||
response_json_paths:
|
||||
endpoint_resp: /api/0.1/item/1
|
||||
endpoint_var: /api/0.1/item/1
|
|
@ -24,12 +24,13 @@ from gabbi import driver
|
|||
from gabbi.driver import test_pytest # noqa
|
||||
from gabbi.tests import simple_wsgi
|
||||
from gabbi.tests import test_intercept
|
||||
from gabbi.tests import util
|
||||
|
||||
TESTS_DIR = 'gabbits_intercept'
|
||||
|
||||
|
||||
def pytest_generate_tests(metafunc):
|
||||
os.environ['GABBI_TEST_URL'] = 'takingnames'
|
||||
util.set_test_environ()
|
||||
test_dir = os.path.join(os.path.dirname(__file__), TESTS_DIR)
|
||||
driver.py_test_generator(
|
||||
test_dir, intercept=simple_wsgi.SimpleWsgi,
|
||||
|
|
|
@ -23,6 +23,7 @@ from gabbi import driver
|
|||
from gabbi import fixture
|
||||
from gabbi.handlers import base
|
||||
from gabbi.tests import simple_wsgi
|
||||
from gabbi.tests import util
|
||||
|
||||
|
||||
TESTS_DIR = 'gabbits_intercept'
|
||||
|
@ -64,7 +65,8 @@ SkipAllFixture = fixture.SkipAllFixture
|
|||
def load_tests(loader, tests, pattern):
|
||||
"""Provide a TestSuite to the discovery process."""
|
||||
# Set and environment variable for one of the tests.
|
||||
os.environ['GABBI_TEST_URL'] = 'takingnames'
|
||||
util.set_test_environ()
|
||||
|
||||
prefix = os.environ.get('GABBI_PREFIX')
|
||||
test_dir = os.path.join(os.path.dirname(__file__), TESTS_DIR)
|
||||
return driver.build_tests(test_dir, loader, host=None,
|
||||
|
|
|
@ -37,8 +37,17 @@ class EnvironReplaceTest(unittest.TestCase):
|
|||
os.environ['moo'] = "False"
|
||||
self.assertEqual(False, http_case._environ_replace(message))
|
||||
|
||||
os.environ['moo'] = "true"
|
||||
self.assertEqual(True, http_case._environ_replace(message))
|
||||
|
||||
os.environ['moo'] = "faLse"
|
||||
self.assertEqual(False, http_case._environ_replace(message))
|
||||
|
||||
os.environ['moo'] = "null"
|
||||
self.assertEqual(None, http_case._environ_replace(message))
|
||||
|
||||
os.environ['moo'] = "1"
|
||||
self.assertEqual("1", http_case._environ_replace(message))
|
||||
self.assertEqual(1, http_case._environ_replace(message))
|
||||
|
||||
os.environ['moo'] = "cow"
|
||||
self.assertEqual("cow", http_case._environ_replace(message))
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
#
|
||||
# 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 methods shared by some tests."""
|
||||
|
||||
import os
|
||||
|
||||
|
||||
def set_test_environ():
|
||||
"""Set some environment variables used in tests."""
|
||||
os.environ['GABBI_TEST_URL'] = 'takingnames'
|
||||
|
||||
# Setup environment variables for `coerce.yaml`
|
||||
os.environ['ONE'] = '1'
|
||||
os.environ['DECIMAL'] = '1.0'
|
||||
os.environ['ARRAY_STRING'] = '[1,2,3]'
|
||||
os.environ['TRUE'] = 'true'
|
||||
os.environ['FALSE'] = 'false'
|
||||
os.environ['STRING'] = 'val'
|
||||
os.environ['NULL'] = 'null'
|
Loading…
Reference in New Issue