Enable a 'url' arg to build_tests (#153)

The value of url overrides host, port and prefix if it is set.
This will make some live testing scenarios more straightforward.

Fixes #50
This commit is contained in:
Chris Dent 2016-06-13 20:10:24 +01:00 committed by GitHub
parent 0a8a3b8faf
commit b6d2689e15
6 changed files with 142 additions and 118 deletions

View File

@ -39,7 +39,8 @@ from gabbi import utils
def build_tests(path, loader, host=None, port=8001, intercept=None,
test_loader_name=None, fixture_module=None,
response_handlers=None, prefix='', require_ssl=False):
response_handlers=None, prefix='', require_ssl=False,
url=None):
"""Read YAML files from a directory to create tests.
Each YAML file represents an ordered sequence of HTTP requests.
@ -54,6 +55,7 @@ def build_tests(path, loader, host=None, port=8001, intercept=None,
:param response_handers: ResponseHandler classes.
:type response_handlers: List of ResponseHandler classes.
:param prefix: A URL prefix for all URLs that are not fully qualified.
:param url: A full URL to test against. Replaces host, port and prefix.
:param require_ssl: If ``True``, make all tests default to using SSL.
:rtype: TestSuite containing multiple TestSuites (one for each YAML file).
"""
@ -63,6 +65,12 @@ def build_tests(path, loader, host=None, port=8001, intercept=None,
if not bool(host) ^ bool(intercept):
raise AssertionError('must specify exactly one of host or intercept')
# If url is being used, reset host, port and prefix.
if url:
host, port, prefix, force_ssl = utils.host_info_from_target(url)
if force_ssl and not require_ssl:
require_ssl = force_ssl
if test_loader_name is None:
test_loader_name = inspect.stack()[1]
test_loader_name = os.path.splitext(os.path.basename(
@ -97,7 +105,7 @@ def build_tests(path, loader, host=None, port=8001, intercept=None,
def py_test_generator(test_dir, host=None, port=8001, intercept=None,
prefix=None, test_loader_name=None,
fixture_module=None, response_handlers=None,
require_ssl=False):
require_ssl=False, url=None):
"""Generate tests cases for py.test
This uses build_tests to create TestCases and then yields them in
@ -110,7 +118,8 @@ def py_test_generator(test_dir, host=None, port=8001, intercept=None,
test_loader_name=test_loader_name,
fixture_module=fixture_module,
response_handlers=response_handlers,
prefix=prefix, require_ssl=require_ssl)
prefix=prefix, require_ssl=require_ssl,
url=url)
for test in tests:
if hasattr(test, '_tests'):

View File

@ -17,8 +17,6 @@ from importlib import import_module
import sys
import unittest
from six.moves.urllib import parse as urlparse
from gabbi import case
from gabbi import handlers
from gabbi.reporter import ConciseTestRunner
@ -93,7 +91,7 @@ def run():
)
args = parser.parse_args()
host, port, prefix, force_ssl = process_target_args(
host, port, prefix, force_ssl = utils.host_info_from_target(
args.target, args.prefix)
# Initialize response handlers.
@ -113,31 +111,6 @@ def run():
sys.exit(not result.wasSuccessful())
def process_target_args(target, prefix):
"""Turn the argparse args into a host, port and prefix."""
force_ssl = False
split_url = urlparse.urlparse(target)
if split_url.scheme:
if split_url.scheme == 'https':
force_ssl = True
return split_url.hostname, split_url.port, split_url.path, force_ssl
else:
target = target
prefix = prefix
if ':' in target and '[' not in target:
host, port = target.rsplit(':', 1)
elif ']:' in target:
host, port = target.rsplit(':', 1)
else:
host = target
port = None
host = host.replace('[', '').replace(']', '')
return host, port, prefix, force_ssl
def initialize_handlers(response_handlers):
custom_response_handlers = []
for import_path in response_handlers or []:

View File

@ -70,3 +70,20 @@ class DriverTest(unittest.TestCase):
first_test = suite._tests[0]._tests[0]
full_url = first_test._parse_url(first_test.test_data['url'])
self.assertEqual('http://localhost:8001/', full_url)
def test_build_url_target(self):
suite = driver.build_tests(self.test_dir, self.loader,
host='localhost', port='999',
url='https://example.com:1024/theend')
first_test = suite._tests[0]._tests[0]
full_url = first_test._parse_url(first_test.test_data['url'])
self.assertEqual('https://example.com:1024/theend/', full_url)
def test_build_url_target_forced_ssl(self):
suite = driver.build_tests(self.test_dir, self.loader,
host='localhost', port='999',
url='http://example.com:1024/theend',
require_ssl=True)
first_test = suite._tests[0]._tests[0]
full_url = first_test._parse_url(first_test.test_data['url'])
self.assertEqual('https://example.com:1024/theend/', full_url)

View File

@ -229,93 +229,6 @@ class RunnerTest(unittest.TestCase):
self._stderr.write(sys.stderr.read())
class RunnerHostArgParse(unittest.TestCase):
def _test_hostport(self, url_or_host, expected_host,
provided_prefix=None, expected_port=None,
expected_prefix=None, expected_ssl=False):
host, port, prefix, ssl = runner.process_target_args(
url_or_host, provided_prefix)
# normalize hosts, they are case insensitive
self.assertEqual(expected_host.lower(), host.lower())
# port can be a string or int depending on the inputs
self.assertEqual(expected_port, port)
self.assertEqual(expected_prefix, prefix)
self.assertEqual(expected_ssl, ssl)
def test_plain_url_no_port(self):
self._test_hostport('http://foobar.com/news',
'foobar.com',
expected_port=None,
expected_prefix='/news')
def test_plain_url_with_port(self):
self._test_hostport('http://foobar.com:80/news',
'foobar.com',
expected_port=80,
expected_prefix='/news')
def test_ssl_url(self):
self._test_hostport('https://foobar.com/news',
'foobar.com',
expected_prefix='/news',
expected_ssl=True)
def test_ssl_port80_url(self):
self._test_hostport('https://foobar.com:80/news',
'foobar.com',
expected_prefix='/news',
expected_port=80,
expected_ssl=True)
def test_ssl_port_url(self):
self._test_hostport('https://foobar.com:999/news',
'foobar.com',
expected_prefix='/news',
expected_port=999,
expected_ssl=True)
def test_simple_hostport(self):
self._test_hostport('foobar.com:999',
'foobar.com',
expected_port='999')
def test_simple_hostport_with_prefix(self):
self._test_hostport('foobar.com:999',
'foobar.com',
provided_prefix='/news',
expected_port='999',
expected_prefix='/news')
def test_ipv6_url_long(self):
self._test_hostport(
'http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:999/news',
'FEDC:BA98:7654:3210:FEDC:BA98:7654:3210',
expected_port=999,
expected_prefix='/news')
def test_ipv6_url_localhost(self):
self._test_hostport(
'http://[::1]:999/news',
'::1',
expected_port=999,
expected_prefix='/news')
def test_ipv6_host_localhost(self):
# If a user wants to use the hostport form, then they need
# to hack it with the brackets.
self._test_hostport(
'[::1]',
'::1')
def test_ipv6_hostport_localhost(self):
self._test_hostport(
'[::1]:999',
'::1',
expected_port='999')
class HTMLResponseHandler(handlers.ResponseHandler):
test_key_suffix = 'html'

View File

@ -158,3 +158,90 @@ class CreateURLTest(unittest.TestCase):
'/foo', 'FEDC:BA98:7654:3210:FEDC:BA98:7654:3210', port=999)
self.assertEqual(
'http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:999/foo', url)
class UtilsHostInfoFromTarget(unittest.TestCase):
def _test_hostport(self, url_or_host, expected_host,
provided_prefix=None, expected_port=None,
expected_prefix=None, expected_ssl=False):
host, port, prefix, ssl = utils.host_info_from_target(
url_or_host, provided_prefix)
# normalize hosts, they are case insensitive
self.assertEqual(expected_host.lower(), host.lower())
# port can be a string or int depending on the inputs
self.assertEqual(expected_port, port)
self.assertEqual(expected_prefix, prefix)
self.assertEqual(expected_ssl, ssl)
def test_plain_url_no_port(self):
self._test_hostport('http://foobar.com/news',
'foobar.com',
expected_port=None,
expected_prefix='/news')
def test_plain_url_with_port(self):
self._test_hostport('http://foobar.com:80/news',
'foobar.com',
expected_port=80,
expected_prefix='/news')
def test_ssl_url(self):
self._test_hostport('https://foobar.com/news',
'foobar.com',
expected_prefix='/news',
expected_ssl=True)
def test_ssl_port80_url(self):
self._test_hostport('https://foobar.com:80/news',
'foobar.com',
expected_prefix='/news',
expected_port=80,
expected_ssl=True)
def test_ssl_port_url(self):
self._test_hostport('https://foobar.com:999/news',
'foobar.com',
expected_prefix='/news',
expected_port=999,
expected_ssl=True)
def test_simple_hostport(self):
self._test_hostport('foobar.com:999',
'foobar.com',
expected_port='999')
def test_simple_hostport_with_prefix(self):
self._test_hostport('foobar.com:999',
'foobar.com',
provided_prefix='/news',
expected_port='999',
expected_prefix='/news')
def test_ipv6_url_long(self):
self._test_hostport(
'http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:999/news',
'FEDC:BA98:7654:3210:FEDC:BA98:7654:3210',
expected_port=999,
expected_prefix='/news')
def test_ipv6_url_localhost(self):
self._test_hostport(
'http://[::1]:999/news',
'::1',
expected_port=999,
expected_prefix='/news')
def test_ipv6_host_localhost(self):
# If a user wants to use the hostport form, then they need
# to hack it with the brackets.
self._test_hostport(
'[::1]',
'::1')
def test_ipv6_hostport_localhost(self):
self._test_hostport(
'[::1]:999',
'::1',
expected_port='999')

View File

@ -126,6 +126,31 @@ def not_binary(content_type):
content_type.startswith('application/json'))
def host_info_from_target(target, prefix=None):
"""Turn url or host:port and target into test destination."""
force_ssl = False
split_url = urlparse.urlparse(target)
if split_url.scheme:
if split_url.scheme == 'https':
force_ssl = True
return split_url.hostname, split_url.port, split_url.path, force_ssl
else:
target = target
prefix = prefix
if ':' in target and '[' not in target:
host, port = target.rsplit(':', 1)
elif ']:' in target:
host, port = target.rsplit(':', 1)
else:
host = target
port = None
host = host.replace('[', '').replace(']', '')
return host, port, prefix, force_ssl
def _colorize(color, message):
"""Add a color to the message."""
try: