
Add a new way of formatting our output in a consistent way. This turns print_list and print_dict into a formatter that has the same API as any other formatter and allows users to create their own formatters and plug them into cratonclient. This includes tests for the base level formatter and our two default formatters as well as some refactoring to allow users to specify their own --format. At the moment, however, the subcommand shells do *not* use the pluggable formatter decided by the user. That change and all of the downstream effects it has on testing is going to be *very* significant and deserves its own commit as this one is large enough. Change-Id: I6649ebce57d5ddf2d4aeb689e77e3c17ef3a2e97
172 lines
6.2 KiB
Python
172 lines
6.2 KiB
Python
# 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.
|
|
"""Tests for the cratonclient.shell.main module."""
|
|
import argparse
|
|
import sys
|
|
|
|
import mock
|
|
import six
|
|
|
|
import cratonclient
|
|
from cratonclient.shell import main
|
|
from cratonclient.tests import base
|
|
|
|
|
|
class TestEntryPoint(base.TestCase):
|
|
"""Tests for the craton shell entry-point."""
|
|
|
|
def setUp(self):
|
|
"""Patch out the CratonShell class."""
|
|
super(TestEntryPoint, self).setUp()
|
|
self.class_mock = mock.patch('cratonclient.shell.main.CratonShell')
|
|
self.craton_shell = self.class_mock.start()
|
|
self.addCleanup(self.class_mock.stop)
|
|
self.print_mock = mock.patch('cratonclient.shell.main.print')
|
|
self.print_func = self.print_mock.start()
|
|
self.addCleanup(self.print_mock.stop)
|
|
self.sys_exit_mock = mock.patch('sys.exit')
|
|
self.sys_exit = self.sys_exit_mock.start()
|
|
self.addCleanup(self.sys_exit_mock.stop)
|
|
|
|
def test_entry_point_creates_a_shell_instance(self):
|
|
"""Verify that our main entry-point uses CratonShell."""
|
|
CratonShell = self.craton_shell
|
|
|
|
main.main()
|
|
|
|
CratonShell.assert_called_once_with()
|
|
|
|
def test_entry_point_calls_shell_main_method(self):
|
|
"""Verify we call the main method on our CratonShell instance."""
|
|
shell_instance = mock.Mock()
|
|
self.craton_shell.return_value = shell_instance
|
|
|
|
main.main()
|
|
|
|
self.assertTrue(shell_instance.main.called)
|
|
|
|
def test_entry_point_converts_args_to_text(self):
|
|
"""Verify we call the main method with a list of text objects."""
|
|
shell_instance = mock.Mock()
|
|
self.craton_shell.return_value = shell_instance
|
|
|
|
main.main()
|
|
|
|
# NOTE(sigmavirus24): call_args is a tuple of positional arguments and
|
|
# keyword arguments, so since we pass a list positionally, we want the
|
|
# first of the positional arguments.
|
|
arglist = shell_instance.main.call_args[0][0]
|
|
self.assertTrue(
|
|
all(isinstance(arg, six.text_type) for arg in arglist)
|
|
)
|
|
|
|
def test_entry_point_handles_all_exceptions(self):
|
|
"""Verify that we handle unexpected exceptions and print a message."""
|
|
shell_instance = mock.Mock()
|
|
shell_instance.main.side_effect = ValueError
|
|
self.craton_shell.return_value = shell_instance
|
|
|
|
main.main()
|
|
|
|
self.print_func.assert_called_once_with(
|
|
"ERROR: ",
|
|
file=sys.stderr,
|
|
)
|
|
|
|
|
|
class TestCratonShell(base.TestCase):
|
|
"""Tests for the CratonShell class."""
|
|
|
|
def setUp(self):
|
|
"""Create an instance of CratonShell for each test."""
|
|
super(TestCratonShell, self).setUp()
|
|
self.shell = main.CratonShell()
|
|
|
|
def test_get_base_parser(self):
|
|
"""Verify how we construct our basic Argument Parser."""
|
|
with mock.patch('argparse.ArgumentParser') as ArgumentParser:
|
|
parser = self.shell.get_base_parser()
|
|
|
|
self.assertEqual(ArgumentParser.return_value, parser)
|
|
ArgumentParser.assert_called_once_with(
|
|
prog='craton',
|
|
description=('Main shell for parsing arguments directed toward '
|
|
'Craton.'),
|
|
epilog='See "craton help COMMAND" for help on a specific command.',
|
|
add_help=False,
|
|
formatter_class=argparse.HelpFormatter,
|
|
)
|
|
|
|
def test_get_base_parser_sets_default_options(self):
|
|
"""Verify how we construct our basic Argument Parser."""
|
|
with mock.patch('cratonclient.common.cliutils.env') as env:
|
|
env.return_value = ''
|
|
with mock.patch('argparse.ArgumentParser'):
|
|
parser = self.shell.get_base_parser()
|
|
|
|
self.assertEqual([
|
|
mock.call(
|
|
'-h', '--help', action='store_true', help=argparse.SUPPRESS,
|
|
),
|
|
mock.call(
|
|
'--version', action='version',
|
|
version=cratonclient.__version__,
|
|
),
|
|
mock.call(
|
|
'--format', default='default', choices=['default', 'json'],
|
|
help=mock.ANY,
|
|
),
|
|
mock.call(
|
|
'--craton-url', default='',
|
|
help='The base URL of the running Craton service. '
|
|
'Defaults to env[CRATON_URL].',
|
|
),
|
|
mock.call(
|
|
'--craton-version', default='',
|
|
type=int,
|
|
help='The version of the Craton API to use. '
|
|
'Defaults to env[CRATON_VERSION].'
|
|
),
|
|
mock.call(
|
|
'--os-project-id', default='',
|
|
help='The project ID used to authenticate to Craton. '
|
|
'Defaults to env[OS_PROJECT_ID].',
|
|
),
|
|
mock.call(
|
|
'--os-username', default='',
|
|
help='The username used to authenticate to Craton. '
|
|
'Defaults to env[OS_USERNAME].',
|
|
),
|
|
mock.call(
|
|
'--os-password', default='',
|
|
help='The password used to authenticate to Craton. '
|
|
'Defaults to env[OS_PASSWORD].',
|
|
),
|
|
],
|
|
parser.add_argument.call_args_list,
|
|
)
|
|
|
|
def test_get_base_parser_retrieves_environment_values(self):
|
|
"""Verify the environment variables that are requested."""
|
|
with mock.patch('cratonclient.common.cliutils.env') as env:
|
|
self.shell.get_base_parser()
|
|
|
|
self.assertEqual([
|
|
mock.call('CRATON_URL'),
|
|
mock.call('CRATON_VERSION', default=1),
|
|
mock.call('OS_PROJECT_ID'),
|
|
mock.call('OS_USERNAME'),
|
|
mock.call('OS_PASSWORD'),
|
|
],
|
|
env.call_args_list,
|
|
)
|