Allowing forcing SSL in build_tests and gabbi-run

build_tests gains a require_ssl argument which, if set to True,
makes all the loaded test suites default to 'ssl: True'.

gabbi-run will interpret a target containing 'https' as meaning
that the tests in the provided yaml should default to 'ssl: True'.

Fixes: #50
Fixes: #105
Fixes: #138

The changes here are the naive basics to get the desired behavior.
There's an existing cleanup branch on which we can clean this up
later.
This commit is contained in:
Chris Dent 2016-06-02 09:15:57 +01:00
parent 5d63f56b6e
commit 08cb8ac1bd
7 changed files with 56 additions and 6 deletions

View File

@ -22,6 +22,8 @@ TESTS_DIR = 'gabbits'
def load_tests(loader, tests, pattern):
"""Provide a TestSuite to the discovery process."""
test_dir = os.path.join(os.path.dirname(__file__), TESTS_DIR)
# Pass "require_ssl=True" as an argument to force all tests
# to use SSL in requests.
return driver.build_tests(test_dir, loader,
intercept=wsgiapp.app,
fixture_module=fixtures)

View File

@ -20,6 +20,8 @@ TESTS_DIR = 'gabbits'
def test_gabbits():
test_dir = os.path.join(os.path.dirname(__file__), TESTS_DIR)
# Pass "require_ssl=True" as an argument to force all tests
# to use SSL in requests.
test_generator = driver.py_test_generator(
test_dir, intercept=wsgiapp.app,
fixture_module=fixtures)

View File

@ -35,5 +35,8 @@ are not fully qualified.
Anywhere host is used, if it is a raw IPV6 address it should be
wrapped in ``[`` and ``]``.
If ``https`` is used in the target, then the tests in the provided
YAML will default to ``ssl: True``.
If a ``-x`` or ``--failfast`` argument is provided then ``gabbi-run`` will
exit after the first test failure.

View File

@ -188,7 +188,7 @@ class TestBuilder(type):
def build_tests(path, loader, host=None, port=8001, intercept=None,
test_loader_name=None, fixture_module=None,
response_handlers=None, prefix=''):
response_handlers=None, prefix='', require_ssl=False):
"""Read YAML files from a directory to create tests.
Each YAML file represents an ordered sequence of HTTP requests.
@ -203,6 +203,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 require_ssl: If ``True``, make all tests default to using SSL.
:rtype: TestSuite containing multiple TestSuites (one for each YAML file).
"""
@ -228,6 +229,13 @@ def build_tests(path, loader, host=None, port=8001, intercept=None,
suite_dict = load_yaml(test_file)
test_base_name = '%s_%s' % (
test_loader_name, os.path.splitext(os.path.basename(test_file))[0])
if require_ssl:
if 'defaults' in suite_dict:
suite_dict['defaults']['ssl'] = True
else:
suite_dict['defaults'] = {'ssl': True}
file_suite = test_suite_from_dict(loader, test_base_name, suite_dict,
path, host, port, fixture_module,
intercept, prefix)
@ -237,7 +245,8 @@ 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):
fixture_module=None, response_handlers=None,
require_ssl=False):
"""Generate tests cases for py.test
This uses build_tests to create TestCases and then yields them in
@ -250,7 +259,7 @@ 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)
prefix=prefix, require_ssl=require_ssl)
for test in tests:
if hasattr(test, '_tests'):

View File

@ -92,10 +92,13 @@ def run():
)
args = parser.parse_args()
force_ssl = False
split_url = urlparse.urlsplit(args.target)
if split_url.scheme:
target = split_url.netloc
prefix = split_url.path
if split_url.scheme == 'https':
force_ssl = True
else:
target = args.target
prefix = args.prefix
@ -118,6 +121,13 @@ def run():
handler(case.HTTPTestCase)
data = yaml.safe_load(sys.stdin.read())
# Only override the default if we are forcing a change, there may
# already be a default.
if force_ssl:
if 'defaults' in data:
data['defaults']['ssl'] = True
else:
data['defaults'] = {'ssl': True}
loader = unittest.defaultTestLoader
suite = driver.test_suite_from_dict(loader, 'input', data, '.',
host, port, None, None,

View File

@ -56,6 +56,21 @@ class DriverTest(unittest.TestCase):
with self.assertRaises(AssertionError):
driver.build_tests(self.test_dir, self.loader)
def test_build_require_ssl(self):
suite = driver.build_tests(self.test_dir, self.loader,
host='localhost',
require_ssl=True)
first_test = suite._tests[0]._tests[0]
full_url = first_test._parse_url(first_test.test_data['url'])
self.assertEqual('https://localhost:8001/', full_url)
suite = driver.build_tests(self.test_dir, self.loader,
host='localhost',
require_ssl=False)
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_tests_key_required(self):
test_yaml = {'name': 'house', 'url': '/'}

View File

@ -228,15 +228,18 @@ class RunnerHostArgParse(unittest.TestCase):
def _test_hostport(self, url_or_host, expected_host,
portmock_yaml, mock_test_suite, mock_read, mock_exit,
provided_prefix=None, expected_port=None,
expected_prefix=None,):
expected_prefix=None, expected_data=None):
sys.argv = ['gabbi-run', url_or_host]
if provided_prefix:
sys.argv.append(provided_prefix)
runner.run()
expected_data = expected_data or {}
mock_test_suite.assert_called_with(
unittest.defaultTestLoader, 'input', {}, '.', expected_host,
expected_port, None, None, prefix=expected_prefix
unittest.defaultTestLoader, 'input', expected_data,
'.', expected_host, expected_port, None, None,
prefix=expected_prefix
)
def test_plain_url(self):
@ -245,6 +248,12 @@ class RunnerHostArgParse(unittest.TestCase):
expected_port='80',
expected_prefix='/news')
def test_ssl_url(self):
self._test_hostport('https://foobar.com/news',
'foobar.com',
expected_prefix='/news',
expected_data={'defaults': {'ssl': True}})
def test_simple_hostport(self):
self._test_hostport('foobar.com:999',
'foobar.com',