covert test suite to use testrepository

Drop the use of nose in favor of testrepository. Set up the gitignore
rules for the output files.

Add coverage reporting to test jobs.

Update tox.ini so the default environments make sense so it is possible
to just run "tox" for local development.

Change-Id: Ieeffdde3bb8a1869af01f5be2bc682a1a834ba13
Signed-off-by: Doug Hellmann <doug@doughellmann.com>
This commit is contained in:
Doug Hellmann 2017-04-23 10:16:30 -04:00
parent d2f23f3aaf
commit c548b7b44c
22 changed files with 2016 additions and 1886 deletions

3
.gitignore vendored
View File

@ -38,3 +38,6 @@ ChangeLog
# Editors # Editors
*~ *~
.*.swp .*.swp
/.testrepository/
/cover/
.coverage.*

7
.testr.conf Normal file
View File

@ -0,0 +1,7 @@
[DEFAULT]
test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \
OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \
OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-60} \
${PYTHON:-python} -m subunit.run discover -t ./ ./cliff $LISTOPT $IDOPTION
test_id_option=--load-list $IDFILE
test_list_option=--list

29
cliff/tests/base.py Normal file
View File

@ -0,0 +1,29 @@
# -*- encoding: utf-8 -*-
#
# 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.
import testtools
import fixtures
class TestBase(testtools.TestCase):
def setUp(self):
super(TestBase, self).setUp()
self._stdout_fixture = fixtures.StringStream('stdout')
self.stdout = self.useFixture(self._stdout_fixture).stream
self.useFixture(fixtures.MonkeyPatch('sys.stdout', self.stdout))
self._stderr_fixture = fixtures.StringStream('stderr')
self.stderr = self.useFixture(self._stderr_fixture).stream
self.useFixture(fixtures.MonkeyPatch('sys.stderr', self.stderr))

View File

@ -13,20 +13,21 @@
# under the License. # under the License.
import argparse import argparse
import codecs
import locale
try: try:
from StringIO import StringIO from StringIO import StringIO
except ImportError: except ImportError:
from io import StringIO from io import StringIO
import sys
import codecs
import locale
import mock import mock
import six import six
import sys
from cliff import app as application from cliff import app as application
from cliff import command as c_cmd from cliff import command as c_cmd
from cliff import commandmanager from cliff import commandmanager
from cliff.tests import base
from cliff.tests import utils as test_utils from cliff.tests import utils as test_utils
from cliff import utils from cliff import utils
@ -59,440 +60,441 @@ def make_app(**kwargs):
return app, command return app, command
def test_no_args_triggers_interactive_mode(): class TestInteractiveMode(base.TestBase):
app, command = make_app()
app.interact = mock.MagicMock(name='inspect') def test_no_args_triggers_interactive_mode(self):
app.run([]) app, command = make_app()
app.interact.assert_called_once_with() app.interact = mock.MagicMock(name='inspect')
app.run([])
app.interact.assert_called_once_with()
def test_interactive_mode_cmdloop(self):
app, command = make_app()
app.interactive_app_factory = mock.MagicMock(
name='interactive_app_factory'
)
self.assertIs(None, app.interpreter)
app.run([])
self.assertIsNot(None, app.interpreter)
cmdloop = app.interactive_app_factory.return_value.cmdloop
cmdloop.assert_called_once_with()
def test_interactive_mode_cmdloop(): class TestInitAndCleanup(base.TestBase):
app, command = make_app()
app.interactive_app_factory = mock.MagicMock( def test_initialize_app(self):
name='interactive_app_factory' app, command = make_app()
) app.initialize_app = mock.MagicMock(name='initialize_app')
assert app.interpreter is None app.run(['mock'])
app.run([]) app.initialize_app.assert_called_once_with(['mock'])
assert app.interpreter is not None
app.interactive_app_factory.return_value.cmdloop.assert_called_once_with() def test_prepare_to_run_command(self):
app, command = make_app()
app.prepare_to_run_command = mock.MagicMock(
name='prepare_to_run_command',
)
app.run(['mock'])
app.prepare_to_run_command.assert_called_once_with(command())
def test_clean_up_success(self):
app, command = make_app()
app.clean_up = mock.MagicMock(name='clean_up')
app.run(['mock'])
app.clean_up.assert_called_once_with(command.return_value, 0, None)
def test_clean_up_error(self):
app, command = make_app()
app.clean_up = mock.MagicMock(name='clean_up')
app.run(['error'])
app.clean_up.assert_called_once_with(mock.ANY, mock.ANY, mock.ANY)
call_args = app.clean_up.call_args_list[0]
self.assertEqual(mock.call(mock.ANY, 1, mock.ANY), call_args)
args, kwargs = call_args
self.assertIsInstance(args[2], RuntimeError)
self.assertEqual(('test exception',), args[2].args)
def test_clean_up_error_debug(self):
app, command = make_app()
app.clean_up = mock.MagicMock(name='clean_up')
try:
app.run(['--debug', 'error'])
except RuntimeError as err:
self.assertIs(err, app.clean_up.call_args_list[0][0][2])
else:
self.fail('Should have had an exception')
self.assertTrue(app.clean_up.called)
call_args = app.clean_up.call_args_list[0]
self.assertEqual(mock.call(mock.ANY, 1, mock.ANY), call_args)
args, kwargs = call_args
self.assertIsInstance(args[2], RuntimeError)
self.assertEqual(('test exception',), args[2].args)
def test_error_handling_clean_up_raises_exception(self):
app, command = make_app()
app.clean_up = mock.MagicMock(
name='clean_up',
side_effect=RuntimeError('within clean_up'),
)
app.run(['error'])
self.assertTrue(app.clean_up.called)
call_args = app.clean_up.call_args_list[0]
self.assertEqual(mock.call(mock.ANY, 1, mock.ANY), call_args)
args, kwargs = call_args
self.assertIsInstance(args[2], RuntimeError)
self.assertEqual(('test exception',), args[2].args)
def test_error_handling_clean_up_raises_exception_debug(self):
app, command = make_app()
app.clean_up = mock.MagicMock(
name='clean_up',
side_effect=RuntimeError('within clean_up'),
)
try:
app.run(['--debug', 'error'])
except RuntimeError as err:
if not hasattr(err, '__context__'):
# The exception passed to clean_up is not the exception
# caused *by* clean_up. This test is only valid in python
# 2 because under v3 the original exception is re-raised
# with the new one as a __context__ attribute.
self.assertIsNot(err, app.clean_up.call_args_list[0][0][2])
else:
self.fail('Should have had an exception')
self.assertTrue(app.clean_up.called)
call_args = app.clean_up.call_args_list[0]
self.assertEqual(mock.call(mock.ANY, 1, mock.ANY), call_args)
args, kwargs = call_args
self.assertIsInstance(args[2], RuntimeError)
self.assertEqual(('test exception',), args[2].args)
def test_normal_clean_up_raises_exception(self):
app, command = make_app()
app.clean_up = mock.MagicMock(
name='clean_up',
side_effect=RuntimeError('within clean_up'),
)
app.run(['mock'])
self.assertTrue(app.clean_up.called)
call_args = app.clean_up.call_args_list[0]
self.assertEqual(mock.call(mock.ANY, 0, None), call_args)
def test_normal_clean_up_raises_exception_debug(self):
app, command = make_app()
app.clean_up = mock.MagicMock(
name='clean_up',
side_effect=RuntimeError('within clean_up'),
)
app.run(['--debug', 'mock'])
self.assertTrue(app.clean_up.called)
call_args = app.clean_up.call_args_list[0]
self.assertEqual(mock.call(mock.ANY, 0, None), call_args)
def test_initialize_app(): class TestOptionParser(base.TestBase):
app, command = make_app()
app.initialize_app = mock.MagicMock(name='initialize_app')
app.run(['mock'])
app.initialize_app.assert_called_once_with(['mock'])
def test_conflicting_option_should_throw(self):
class MyApp(application.App):
def __init__(self):
super(MyApp, self).__init__(
description='testing',
version='0.1',
command_manager=commandmanager.CommandManager('tests'),
)
def test_prepare_to_run_command(): def build_option_parser(self, description, version):
app, command = make_app() parser = super(MyApp, self).build_option_parser(description,
app.prepare_to_run_command = mock.MagicMock(name='prepare_to_run_command') version)
app.run(['mock']) parser.add_argument(
app.prepare_to_run_command.assert_called_once_with(command()) '-h', '--help',
default=self, # tricky
help="Show help message and exit.",
)
self.assertRaises(
argparse.ArgumentError,
MyApp,
)
def test_clean_up_success(): def test_conflicting_option_custom_arguments_should_not_throw(self):
app, command = make_app() class MyApp(application.App):
app.clean_up = mock.MagicMock(name='clean_up') def __init__(self):
app.run(['mock']) super(MyApp, self).__init__(
app.clean_up.assert_called_once_with(command.return_value, 0, None) description='testing',
version='0.1',
command_manager=commandmanager.CommandManager('tests'),
)
def build_option_parser(self, description, version):
argparse_kwargs = {'conflict_handler': 'resolve'}
parser = super(MyApp, self).build_option_parser(
description,
version,
argparse_kwargs=argparse_kwargs)
parser.add_argument(
'-h', '--help',
default=self, # tricky
help="Show help message and exit.",
)
def test_clean_up_error():
app, command = make_app()
app.clean_up = mock.MagicMock(name='clean_up')
app.run(['error'])
app.clean_up.assert_called_once_with(mock.ANY, mock.ANY, mock.ANY)
call_args = app.clean_up.call_args_list[0]
assert call_args == mock.call(mock.ANY, 1, mock.ANY)
args, kwargs = call_args
assert isinstance(args[2], RuntimeError)
assert args[2].args == ('test exception',)
def test_clean_up_error_debug():
app, command = make_app()
app.clean_up = mock.MagicMock(name='clean_up')
try:
app.run(['--debug', 'error'])
except RuntimeError as err:
assert app.clean_up.call_args_list[0][0][2] is err
else:
assert False, 'Should have had an exception'
assert app.clean_up.called
call_args = app.clean_up.call_args_list[0]
assert call_args == mock.call(mock.ANY, 1, mock.ANY)
args, kwargs = call_args
assert isinstance(args[2], RuntimeError)
assert args[2].args == ('test exception',)
def test_error_handling_clean_up_raises_exception():
app, command = make_app()
app.clean_up = mock.MagicMock(
name='clean_up',
side_effect=RuntimeError('within clean_up'),
)
app.run(['error'])
assert app.clean_up.called
call_args = app.clean_up.call_args_list[0]
assert call_args == mock.call(mock.ANY, 1, mock.ANY)
args, kwargs = call_args
assert isinstance(args[2], RuntimeError)
assert args[2].args == ('test exception',)
def test_error_handling_clean_up_raises_exception_debug():
app, command = make_app()
app.clean_up = mock.MagicMock(
name='clean_up',
side_effect=RuntimeError('within clean_up'),
)
try:
app.run(['--debug', 'error'])
except RuntimeError as err:
if not hasattr(err, '__context__'):
# The exception passed to clean_up is not the exception
# caused *by* clean_up. This test is only valid in python
# 2 because under v3 the original exception is re-raised
# with the new one as a __context__ attribute.
assert app.clean_up.call_args_list[0][0][2] is not err
else:
assert False, 'Should have had an exception'
assert app.clean_up.called
call_args = app.clean_up.call_args_list[0]
assert call_args == mock.call(mock.ANY, 1, mock.ANY)
args, kwargs = call_args
assert isinstance(args[2], RuntimeError)
assert args[2].args == ('test exception',)
def test_normal_clean_up_raises_exception():
app, command = make_app()
app.clean_up = mock.MagicMock(
name='clean_up',
side_effect=RuntimeError('within clean_up'),
)
app.run(['mock'])
assert app.clean_up.called
call_args = app.clean_up.call_args_list[0]
assert call_args == mock.call(mock.ANY, 0, None)
def test_normal_clean_up_raises_exception_debug():
app, command = make_app()
app.clean_up = mock.MagicMock(
name='clean_up',
side_effect=RuntimeError('within clean_up'),
)
app.run(['--debug', 'mock'])
assert app.clean_up.called
call_args = app.clean_up.call_args_list[0]
assert call_args == mock.call(mock.ANY, 0, None)
def test_build_option_parser_conflicting_option_should_throw():
class MyApp(application.App):
def __init__(self):
super(MyApp, self).__init__(
description='testing',
version='0.1',
command_manager=commandmanager.CommandManager('tests'),
)
def build_option_parser(self, description, version):
parser = super(MyApp, self).build_option_parser(description,
version)
parser.add_argument(
'-h', '--help',
default=self, # tricky
help="Show help message and exit.",
)
# TODO: tests should really use unittest2.
try:
MyApp() MyApp()
except argparse.ArgumentError:
pass def test_option_parser_abbrev_issue(self):
else: class MyCommand(c_cmd.Command):
raise Exception('Exception was not thrown') def get_parser(self, prog_name):
parser = super(MyCommand, self).get_parser(prog_name)
parser.add_argument("--end")
return parser
def take_action(self, parsed_args):
assert(parsed_args.end == '123')
class MyCommandManager(commandmanager.CommandManager):
def load_commands(self, namespace):
self.add_command("mycommand", MyCommand)
class MyApp(application.App):
def __init__(self):
super(MyApp, self).__init__(
description='testing',
version='0.1',
command_manager=MyCommandManager(None),
)
def build_option_parser(self, description, version):
parser = super(MyApp, self).build_option_parser(
description,
version,
argparse_kwargs={'allow_abbrev': False})
parser.add_argument('--endpoint')
return parser
app = MyApp()
# NOTE(jd) --debug is necessary so assert in take_action()
# raises correctly here
app.run(['--debug', 'mycommand', '--end', '123'])
def test_option_parser_conflicting_option_custom_arguments_should_not_throw(): class TestHelpHandling(base.TestBase):
class MyApp(application.App):
def __init__(self): def _test_help(self, deferred_help):
super(MyApp, self).__init__( app, _ = make_app(deferred_help=deferred_help)
description='testing', with mock.patch.object(app, 'initialize_app') as init:
version='0.1', with mock.patch('cliff.help.HelpAction.__call__',
command_manager=commandmanager.CommandManager('tests'), side_effect=SystemExit(0)) as helper:
self.assertRaises(
SystemExit,
app.run,
['--help'],
)
self.assertTrue(helper.called)
self.assertEqual(deferred_help, init.called)
def test_help(self):
self._test_help(False)
def test_deferred_help(self):
self._test_help(True)
def test_subcommand_help(self):
app, _ = make_app(deferred_help=False)
# Help is called immediately
with mock.patch('cliff.help.HelpAction.__call__') as helper:
app.run(['show', 'files', '--help'])
self.assertTrue(helper.called)
def test_subcommand_deferred_help(self):
app, _ = make_app(deferred_help=True)
# Show that provide_help_if_requested() did not show help and exit
with mock.patch.object(app, 'run_subcommand') as helper:
app.run(['show', 'files', '--help'])
helper.assert_called_once_with(['help', 'show', 'files'])
class TestCommandLookup(base.TestBase):
def test_unknown_cmd(self):
app, command = make_app()
self.assertEqual(2, app.run(['hell']))
def test_unknown_cmd_debug(self):
app, command = make_app()
try:
self.assertEqual(2, app.run(['--debug', 'hell']))
except ValueError as err:
self.assertIn("['hell']", str(err))
def test_list_matching_commands(self):
stdout = StringIO()
app = application.App('testing', '1',
test_utils.TestCommandManager(
test_utils.TEST_NAMESPACE),
stdout=stdout)
app.NAME = 'test'
try:
self.assertEqual(2, app.run(['t']))
except SystemExit:
pass
output = stdout.getvalue()
self.assertIn("test: 't' is not a test command. See 'test --help'.",
output)
self.assertIn('Did you mean one of these?', output)
self.assertIn('three word command\n two words\n', output)
def test_fuzzy_no_commands(self):
cmd_mgr = commandmanager.CommandManager('cliff.fuzzy')
app = application.App('test', '1.0', cmd_mgr)
cmd_mgr.commands = {}
matches = app.get_fuzzy_matches('foo')
self.assertEqual([], matches)
def test_fuzzy_common_prefix(self):
# searched string is a prefix of all commands
cmd_mgr = commandmanager.CommandManager('cliff.fuzzy')
app = application.App('test', '1.0', cmd_mgr)
cmd_mgr.commands = {}
cmd_mgr.add_command('user list', test_utils.TestCommand)
cmd_mgr.add_command('user show', test_utils.TestCommand)
matches = app.get_fuzzy_matches('user')
self.assertEqual(['user list', 'user show'], matches)
def test_fuzzy_same_distance(self):
# searched string has the same distance to all commands
cmd_mgr = commandmanager.CommandManager('cliff.fuzzy')
app = application.App('test', '1.0', cmd_mgr)
cmd_mgr.add_command('user', test_utils.TestCommand)
for cmd in cmd_mgr.commands.keys():
self.assertEqual(
8,
utils.damerau_levenshtein('node', cmd, utils.COST),
) )
matches = app.get_fuzzy_matches('node')
self.assertEqual(['complete', 'help', 'user'], matches)
def build_option_parser(self, description, version): def test_fuzzy_no_prefix(self):
argparse_kwargs = {'conflict_handler': 'resolve'} # search by distance, no common prefix with any command
parser = super(MyApp, self).build_option_parser( cmd_mgr = commandmanager.CommandManager('cliff.fuzzy')
description, app = application.App('test', '1.0', cmd_mgr)
version, cmd_mgr.add_command('user', test_utils.TestCommand)
argparse_kwargs=argparse_kwargs) matches = app.get_fuzzy_matches('uesr')
parser.add_argument( self.assertEqual(['user'], matches)
'-h', '--help',
default=self, # tricky
help="Show help message and exit.",
)
MyApp()
def test_option_parser_abbrev_issue(): class TestVerboseMode(base.TestBase):
class MyCommand(c_cmd.Command):
def get_parser(self, prog_name):
parser = super(MyCommand, self).get_parser(prog_name)
parser.add_argument("--end")
return parser
def take_action(self, parsed_args): def test_verbose(self):
assert(parsed_args.end == '123') app, command = make_app()
app.clean_up = mock.MagicMock(name='clean_up')
class MyCommandManager(commandmanager.CommandManager): app.run(['--verbose', 'mock'])
def load_commands(self, namespace): app.clean_up.assert_called_once_with(command.return_value, 0, None)
self.add_command("mycommand", MyCommand) app.clean_up.reset_mock()
app.run(['--quiet', 'mock'])
class MyApp(application.App): app.clean_up.assert_called_once_with(command.return_value, 0, None)
def __init__(self): self.assertRaises(
super(MyApp, self).__init__( SystemExit,
description='testing', app.run,
version='0.1', ['--verbose', '--quiet', 'mock'],
command_manager=MyCommandManager(None), )
)
def build_option_parser(self, description, version):
parser = super(MyApp, self).build_option_parser(
description,
version,
argparse_kwargs={'allow_abbrev': False})
parser.add_argument('--endpoint')
return parser
app = MyApp()
# NOTE(jd) --debug is necessary so assert in take_action() raises correctly
# here
app.run(['--debug', 'mycommand', '--end', '123'])
def _test_help(deferred_help): class TestIO(base.TestBase):
app, _ = make_app(deferred_help=deferred_help)
with mock.patch.object(app, 'initialize_app') as init: def test_io_streams(self):
with mock.patch('cliff.help.HelpAction.__call__', cmd_mgr = commandmanager.CommandManager('cliff.tests')
side_effect=SystemExit(0)) as helper: io = mock.Mock()
if six.PY2:
stdin_save = sys.stdin
stdout_save = sys.stdout
stderr_save = sys.stderr
encoding = locale.getpreferredencoding() or 'utf-8'
app = application.App('no io streams', 1, cmd_mgr)
self.assertIsInstance(app.stdin, codecs.StreamReader)
self.assertIsInstance(app.stdout, codecs.StreamWriter)
self.assertIsInstance(app.stderr, codecs.StreamWriter)
app = application.App('with stdin io stream', 1, cmd_mgr, stdin=io)
self.assertIs(io, app.stdin)
self.assertIsInstance(app.stdout, codecs.StreamWriter)
self.assertIsInstance(app.stderr, codecs.StreamWriter)
app = application.App('with stdout io stream', 1, cmd_mgr,
stdout=io)
self.assertIsInstance(app.stdin, codecs.StreamReader)
self.assertIs(io, app.stdout)
self.assertIsInstance(app.stderr, codecs.StreamWriter)
app = application.App('with stderr io stream', 1, cmd_mgr,
stderr=io)
self.assertIsInstance(app.stdin, codecs.StreamReader)
self.assertIsInstance(app.stdout, codecs.StreamWriter)
self.assertIs(io, app.stderr)
try: try:
app.run(['--help']) sys.stdin = codecs.getreader(encoding)(sys.stdin)
except SystemExit: app = application.App(
pass 'with wrapped sys.stdin io stream', 1, cmd_mgr)
else: self.assertIs(sys.stdin, app.stdin)
raise Exception('Exception was not thrown') self.assertIsInstance(app.stdout, codecs.StreamWriter)
assert helper.called self.assertIsInstance(app.stderr, codecs.StreamWriter)
assert init.called == deferred_help finally:
sys.stdin = stdin_save
try:
sys.stdout = codecs.getwriter(encoding)(sys.stdout)
app = application.App('with wrapped stdout io stream', 1,
cmd_mgr)
self.assertIsInstance(app.stdin, codecs.StreamReader)
self.assertIs(sys.stdout, app.stdout)
self.assertIsInstance(app.stderr, codecs.StreamWriter)
finally:
sys.stdout = stdout_save
def test_help(): try:
_test_help(False) sys.stderr = codecs.getwriter(encoding)(sys.stderr)
app = application.App('with wrapped stderr io stream', 1,
cmd_mgr)
self.assertIsInstance(app.stdin, codecs.StreamReader)
self.assertIsInstance(app.stdout, codecs.StreamWriter)
self.assertIs(sys.stderr, app.stderr)
finally:
sys.stderr = stderr_save
else:
app = application.App('no io streams', 1, cmd_mgr)
self.assertIs(sys.stdin, app.stdin)
self.assertIs(sys.stdout, app.stdout)
self.assertIs(sys.stderr, app.stderr)
def test_deferred_help(): app = application.App('with stdin io stream', 1, cmd_mgr, stdin=io)
_test_help(True) self.assertIs(io, app.stdin)
self.assertIs(sys.stdout, app.stdout)
self.assertIs(sys.stderr, app.stderr)
app = application.App('with stdout io stream', 1, cmd_mgr,
stdout=io)
self.assertIs(sys.stdin, app.stdin)
self.assertIs(io, app.stdout)
self.assertIs(sys.stderr, app.stderr)
def test_subcommand_help(): app = application.App('with stderr io stream', 1, cmd_mgr,
app, _ = make_app(deferred_help=False) stderr=io)
self.assertIs(sys.stdin, app.stdin)
# Help is called immediately self.assertIs(sys.stdout, app.stdout)
with mock.patch('cliff.help.HelpAction.__call__') as helper: self.assertIs(io, app.stderr)
app.run(['show', 'files', '--help'])
assert helper.called
def test_subcommand_deferred_help():
app, _ = make_app(deferred_help=True)
# Show that provide_help_if_requested() did not show help and exit
with mock.patch.object(app, 'run_subcommand') as helper:
app.run(['show', 'files', '--help'])
helper.assert_called_once_with(['help', 'show', 'files'])
def test_unknown_cmd():
app, command = make_app()
assert app.run(['hell']) == 2
def test_unknown_cmd_debug():
app, command = make_app()
try:
app.run(['--debug', 'hell']) == 2
except ValueError as err:
assert "['hell']" in ('%s' % err)
def test_list_matching_commands():
stdout = StringIO()
app = application.App('testing', '1',
test_utils.TestCommandManager(
test_utils.TEST_NAMESPACE),
stdout=stdout)
app.NAME = 'test'
try:
assert app.run(['t']) == 2
except SystemExit:
pass
output = stdout.getvalue()
assert "test: 't' is not a test command. See 'test --help'." in output
assert 'Did you mean one of these?' in output
assert 'three word command\n two words\n' in output
def test_fuzzy_no_commands():
cmd_mgr = commandmanager.CommandManager('cliff.fuzzy')
app = application.App('test', '1.0', cmd_mgr)
cmd_mgr.commands = {}
matches = app.get_fuzzy_matches('foo')
assert matches == []
def test_fuzzy_common_prefix():
# searched string is a prefix of all commands
cmd_mgr = commandmanager.CommandManager('cliff.fuzzy')
app = application.App('test', '1.0', cmd_mgr)
cmd_mgr.commands = {}
cmd_mgr.add_command('user list', test_utils.TestCommand)
cmd_mgr.add_command('user show', test_utils.TestCommand)
matches = app.get_fuzzy_matches('user')
assert matches == ['user list', 'user show']
def test_fuzzy_same_distance():
# searched string has the same distance to all commands
cmd_mgr = commandmanager.CommandManager('cliff.fuzzy')
app = application.App('test', '1.0', cmd_mgr)
cmd_mgr.add_command('user', test_utils.TestCommand)
for cmd in cmd_mgr.commands.keys():
assert utils.damerau_levenshtein('node', cmd, utils.COST) == 8
matches = app.get_fuzzy_matches('node')
assert matches == ['complete', 'help', 'user']
def test_fuzzy_no_prefix():
# search by distance, no common prefix with any command
cmd_mgr = commandmanager.CommandManager('cliff.fuzzy')
app = application.App('test', '1.0', cmd_mgr)
cmd_mgr.add_command('user', test_utils.TestCommand)
matches = app.get_fuzzy_matches('uesr')
assert matches == ['user']
def test_verbose():
app, command = make_app()
app.clean_up = mock.MagicMock(name='clean_up')
app.run(['--verbose', 'mock'])
app.clean_up.assert_called_once_with(command.return_value, 0, None)
app.clean_up.reset_mock()
app.run(['--quiet', 'mock'])
app.clean_up.assert_called_once_with(command.return_value, 0, None)
try:
app.run(['--verbose', '--quiet', 'mock'])
except SystemExit:
pass
else:
raise Exception('Exception was not thrown')
def test_io_streams():
cmd_mgr = commandmanager.CommandManager('cliff.tests')
io = mock.Mock()
if six.PY2:
stdin_save = sys.stdin
stdout_save = sys.stdout
stderr_save = sys.stderr
encoding = locale.getpreferredencoding() or 'utf-8'
app = application.App('no io streams', 1, cmd_mgr)
assert isinstance(app.stdin, codecs.StreamReader)
assert isinstance(app.stdout, codecs.StreamWriter)
assert isinstance(app.stderr, codecs.StreamWriter)
app = application.App('with stdin io stream', 1, cmd_mgr, stdin=io)
assert app.stdin is io
assert isinstance(app.stdout, codecs.StreamWriter)
assert isinstance(app.stderr, codecs.StreamWriter)
app = application.App('with stdout io stream', 1, cmd_mgr, stdout=io)
assert isinstance(app.stdin, codecs.StreamReader)
assert app.stdout is io
assert isinstance(app.stderr, codecs.StreamWriter)
app = application.App('with stderr io stream', 1, cmd_mgr, stderr=io)
assert isinstance(app.stdin, codecs.StreamReader)
assert isinstance(app.stdout, codecs.StreamWriter)
assert app.stderr is io
try:
sys.stdin = codecs.getreader(encoding)(sys.stdin)
app = application.App(
'with wrapped sys.stdin io stream', 1, cmd_mgr)
assert app.stdin is sys.stdin
assert isinstance(app.stdout, codecs.StreamWriter)
assert isinstance(app.stderr, codecs.StreamWriter)
finally:
sys.stdin = stdin_save
try:
sys.stdout = codecs.getwriter(encoding)(sys.stdout)
app = application.App('with wrapped stdout io stream', 1, cmd_mgr)
assert isinstance(app.stdin, codecs.StreamReader)
assert app.stdout is sys.stdout
assert isinstance(app.stderr, codecs.StreamWriter)
finally:
sys.stdout = stdout_save
try:
sys.stderr = codecs.getwriter(encoding)(sys.stderr)
app = application.App('with wrapped stderr io stream', 1, cmd_mgr)
assert isinstance(app.stdin, codecs.StreamReader)
assert isinstance(app.stdout, codecs.StreamWriter)
assert app.stderr is sys.stderr
finally:
sys.stderr = stderr_save
else:
app = application.App('no io streams', 1, cmd_mgr)
assert app.stdin is sys.stdin
assert app.stdout is sys.stdout
assert app.stderr is sys.stderr
app = application.App('with stdin io stream', 1, cmd_mgr, stdin=io)
assert app.stdin is io
assert app.stdout is sys.stdout
assert app.stderr is sys.stderr
app = application.App('with stdout io stream', 1, cmd_mgr, stdout=io)
assert app.stdin is sys.stdin
assert app.stdout is io
assert app.stderr is sys.stderr
app = application.App('with stderr io stream', 1, cmd_mgr, stderr=io)
assert app.stdin is sys.stdin
assert app.stdout is sys.stdout
assert app.stderr is io

View File

@ -10,6 +10,8 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import unittest
from cliff import columns from cliff import columns
@ -19,12 +21,15 @@ class FauxColumn(columns.FormattableColumn):
return u'I made this string myself: {}'.format(self._value) return u'I made this string myself: {}'.format(self._value)
def test_faux_column_machine(): class TestColumns(unittest.TestCase):
c = FauxColumn(['list', 'of', 'values'])
assert c.machine_readable() == ['list', 'of', 'values']
def test_faux_column_machine(self):
c = FauxColumn(['list', 'of', 'values'])
self.assertEqual(['list', 'of', 'values'], c.machine_readable())
def test_faux_column_human(): def test_faux_column_human(self):
c = FauxColumn(['list', 'of', 'values']) c = FauxColumn(['list', 'of', 'values'])
assert c.human_readable() == \ self.assertEqual(
u"I made this string myself: ['list', 'of', 'values']" u"I made this string myself: ['list', 'of', 'values']",
c.human_readable(),
)

View File

@ -11,6 +11,7 @@
# under the License. # under the License.
from cliff import command from cliff import command
from cliff.tests import base
class TestCommand(command.Command): class TestCommand(command.Command):
@ -51,47 +52,44 @@ class TestCommandNoDocstring(command.Command):
return 42 return 42
def test_get_description_docstring(): class TestDescription(base.TestBase):
cmd = TestCommand(None, None)
desc = cmd.get_description() def test_get_description_docstring(self):
assert desc == "Description of command.\n " cmd = TestCommand(None, None)
desc = cmd.get_description()
assert desc == "Description of command.\n "
def test_get_description_attribute(self):
cmd = TestCommand(None, None)
# Artificially inject a value for _description to verify that it
# overrides the docstring.
cmd._description = 'this is not the default'
desc = cmd.get_description()
assert desc == 'this is not the default'
def test_get_description_default(self):
cmd = TestCommandNoDocstring(None, None)
desc = cmd.get_description()
assert desc == ''
def test_get_description_attribute(): class TestBasicValues(base.TestBase):
cmd = TestCommand(None, None)
# Artificially inject a value for _description to verify that it def test_get_parser(self):
# overrides the docstring. cmd = TestCommand(None, None)
cmd._description = 'this is not the default' parser = cmd.get_parser('NAME')
desc = cmd.get_description() assert parser.prog == 'NAME'
assert desc == 'this is not the default'
def test_get_name(self):
cmd = TestCommand(None, None, cmd_name='object action')
assert cmd.cmd_name == 'object action'
def test_run_return(self):
cmd = TestCommand(None, None, cmd_name='object action')
assert cmd.run(None) == 42
def test_get_description_default(): expected_help_message = """
cmd = TestCommandNoDocstring(None, None)
desc = cmd.get_description()
assert desc == ''
def test_get_parser():
cmd = TestCommand(None, None)
parser = cmd.get_parser('NAME')
assert parser.prog == 'NAME'
def test_get_name():
cmd = TestCommand(None, None, cmd_name='object action')
assert cmd.cmd_name == 'object action'
def test_run_return():
cmd = TestCommand(None, None, cmd_name='object action')
assert cmd.run(None) == 42
def test_smart_help_formatter():
cmd = TestCommand(None, None)
parser = cmd.get_parser('NAME')
expected_help_message = """
long_help_argument Create a NIC on the server. long_help_argument Create a NIC on the server.
Specify option multiple times to create multiple NICs. Specify option multiple times to create multiple NICs.
Either net-id or port-id must be provided, but not Either net-id or port-id must be provided, but not
@ -108,4 +106,11 @@ def test_smart_help_formatter():
regular_help_argument regular_help_argument
The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.
""" """
assert expected_help_message in parser.format_help()
class TestHelp(base.TestBase):
def test_smart_help_formatter(self):
cmd = TestCommand(None, None)
parser = cmd.get_parser('NAME')
self.assertIn(expected_help_message, parser.format_help())

View File

@ -11,122 +11,142 @@
# under the License. # under the License.
import mock import mock
import testscenarios
from cliff import commandmanager from cliff import commandmanager
from cliff.tests import base
from cliff.tests import utils from cliff.tests import utils
def test_lookup_and_find(): load_tests = testscenarios.load_tests_apply_scenarios
def check(mgr, argv):
cmd, name, remaining = mgr.find_command(argv)
assert cmd
assert name == ' '.join(argv)
assert not remaining
mgr = utils.TestCommandManager(utils.TEST_NAMESPACE)
for expected in [['one'],
['two', 'words'],
['three', 'word', 'command'],
]:
yield check, mgr, expected
return
def test_lookup_with_remainder(): class TestLookupAndFind(base.TestBase):
def check(mgr, argv):
cmd, name, remaining = mgr.find_command(argv) scenarios = [
assert cmd ('one-word', {'argv': ['one']}),
assert remaining == ['--opt'] ('two-words', {'argv': ['two', 'words']}),
mgr = utils.TestCommandManager(utils.TEST_NAMESPACE) ('three-words', {'argv': ['three', 'word', 'command']}),
for expected in [['one', '--opt'], ]
['two', 'words', '--opt'],
['three', 'word', 'command', '--opt'], def test(self):
]: mgr = utils.TestCommandManager(utils.TEST_NAMESPACE)
yield check, mgr, expected cmd, name, remaining = mgr.find_command(self.argv)
return self.assertTrue(cmd)
self.assertEqual(' '.join(self.argv), name)
self.assertFalse(remaining)
def test_find_invalid_command(): class TestLookupWithRemainder(base.TestBase):
mgr = utils.TestCommandManager(utils.TEST_NAMESPACE)
def check_one(argv): scenarios = [
('one', {'argv': ['one', '--opt']}),
('two', {'argv': ['two', 'words', '--opt']}),
('three', {'argv': ['three', 'word', 'command', '--opt']}),
]
def test(self):
mgr = utils.TestCommandManager(utils.TEST_NAMESPACE)
cmd, name, remaining = mgr.find_command(self.argv)
self.assertTrue(cmd)
self.assertEqual(['--opt'], remaining)
class TestFindInvalidCommand(base.TestBase):
scenarios = [
('no-such-command', {'argv': ['a', '-b']}),
('no-command-given', {'argv': ['-b']}),
]
def test(self):
mgr = utils.TestCommandManager(utils.TEST_NAMESPACE)
try: try:
mgr.find_command(argv) mgr.find_command(self.argv)
except ValueError as err: except ValueError as err:
# make sure err include 'a' when ['a', '-b'] # make sure err include 'a' when ['a', '-b']
assert argv[0] in ('%s' % err) self.assertIn(self.argv[0], str(err))
assert '-b' in ('%s' % err) self.assertIn('-b', str(err))
else: else:
assert False, 'expected a failure' self.fail('expected a failure')
for argv in [['a', '-b'],
['-b'],
]:
yield check_one, argv
def test_find_unknown_command(): class TestFindUnknownCommand(base.TestBase):
mgr = utils.TestCommandManager(utils.TEST_NAMESPACE)
try: def test(self):
mgr.find_command(['a', 'b']) mgr = utils.TestCommandManager(utils.TEST_NAMESPACE)
except ValueError as err: try:
assert "['a', 'b']" in ('%s' % err) mgr.find_command(['a', 'b'])
else: except ValueError as err:
assert False, 'expected a failure' self.assertIn("['a', 'b']", str(err))
else:
self.fail('expected a failure')
def test_add_command(): class TestDynamicCommands(base.TestBase):
mgr = utils.TestCommandManager(utils.TEST_NAMESPACE)
mock_cmd = mock.Mock() def test_add(self):
mgr.add_command('mock', mock_cmd) mgr = utils.TestCommandManager(utils.TEST_NAMESPACE)
found_cmd, name, args = mgr.find_command(['mock']) mock_cmd = mock.Mock()
assert found_cmd is mock_cmd mgr.add_command('mock', mock_cmd)
found_cmd, name, args = mgr.find_command(['mock'])
self.assertIs(mock_cmd, found_cmd)
def test_intersected_commands(self):
def foo(arg):
pass
def foo_bar():
pass
mgr = utils.TestCommandManager(utils.TEST_NAMESPACE)
mgr.add_command('foo', foo)
mgr.add_command('foo bar', foo_bar)
self.assertIs(foo_bar, mgr.find_command(['foo', 'bar'])[0])
self.assertIs(
foo,
mgr.find_command(['foo', 'arg0'])[0],
)
def test_intersected_commands(): class TestLoad(base.TestBase):
def foo(arg):
pass
def foo_bar(): def test_load_commands(self):
pass testcmd = mock.Mock(name='testcmd')
testcmd.name.replace.return_value = 'test'
mock_pkg_resources = mock.Mock(return_value=[testcmd])
with mock.patch('pkg_resources.iter_entry_points',
mock_pkg_resources) as iter_entry_points:
mgr = commandmanager.CommandManager('test')
iter_entry_points.assert_called_once_with('test')
names = [n for n, v in mgr]
self.assertEqual(['test'], names)
mgr = utils.TestCommandManager(utils.TEST_NAMESPACE) def test_load_commands_keep_underscores(self):
mgr.add_command('foo', foo) testcmd = mock.Mock()
mgr.add_command('foo bar', foo_bar) testcmd.name = 'test_cmd'
mock_pkg_resources = mock.Mock(return_value=[testcmd])
with mock.patch('pkg_resources.iter_entry_points',
mock_pkg_resources) as iter_entry_points:
mgr = commandmanager.CommandManager(
'test',
convert_underscores=False,
)
iter_entry_points.assert_called_once_with('test')
names = [n for n, v in mgr]
self.assertEqual(['test_cmd'], names)
assert mgr.find_command(['foo', 'bar'])[0] is foo_bar def test_load_commands_replace_underscores(self):
assert mgr.find_command(['foo', 'arg0'])[0] is foo testcmd = mock.Mock()
testcmd.name = 'test_cmd'
mock_pkg_resources = mock.Mock(return_value=[testcmd])
def test_load_commands(): with mock.patch('pkg_resources.iter_entry_points',
testcmd = mock.Mock(name='testcmd') mock_pkg_resources) as iter_entry_points:
testcmd.name.replace.return_value = 'test' mgr = commandmanager.CommandManager(
mock_pkg_resources = mock.Mock(return_value=[testcmd]) 'test',
with mock.patch('pkg_resources.iter_entry_points', convert_underscores=True,
mock_pkg_resources) as iter_entry_points: )
mgr = commandmanager.CommandManager('test') iter_entry_points.assert_called_once_with('test')
iter_entry_points.assert_called_once_with('test') names = [n for n, v in mgr]
names = [n for n, v in mgr] self.assertEqual(['test cmd'], names)
assert names == ['test']
def test_load_commands_keep_underscores():
testcmd = mock.Mock()
testcmd.name = 'test_cmd'
mock_pkg_resources = mock.Mock(return_value=[testcmd])
with mock.patch('pkg_resources.iter_entry_points',
mock_pkg_resources) as iter_entry_points:
mgr = commandmanager.CommandManager('test', convert_underscores=False)
iter_entry_points.assert_called_once_with('test')
names = [n for n, v in mgr]
assert names == ['test_cmd']
def test_load_commands_replace_underscores():
testcmd = mock.Mock()
testcmd.name = 'test_cmd'
mock_pkg_resources = mock.Mock(return_value=[testcmd])
with mock.patch('pkg_resources.iter_entry_points',
mock_pkg_resources) as iter_entry_points:
mgr = commandmanager.CommandManager('test', convert_underscores=True)
iter_entry_points.assert_called_once_with('test')
names = [n for n, v in mgr]
assert names == ['test cmd']

View File

@ -18,50 +18,52 @@ import mock
from cliff import app as application from cliff import app as application
from cliff import commandmanager from cliff import commandmanager
from cliff import complete from cliff import complete
from cliff.tests import base
def test_complete_dictionary(): class TestCompletion(base.TestBase):
sot = complete.CompleteDictionary()
sot.add_command("image delete".split(),
[mock.Mock(option_strings=["1"])])
sot.add_command("image list".split(),
[mock.Mock(option_strings=["2"])])
sot.add_command("image create".split(),
[mock.Mock(option_strings=["3"])])
sot.add_command("volume type create".split(),
[mock.Mock(option_strings=["4"])])
sot.add_command("volume type delete".split(),
[mock.Mock(option_strings=["5"])])
assert "image volume" == sot.get_commands()
result = sot.get_data()
assert "image" == result[0][0]
assert "create delete list" == result[0][1]
assert "image_create" == result[1][0]
assert "3" == result[1][1]
assert "image_delete" == result[2][0]
assert "1" == result[2][1]
assert "image_list" == result[3][0]
assert "2" == result[3][1]
def test_dictionary(self):
sot = complete.CompleteDictionary()
sot.add_command("image delete".split(),
[mock.Mock(option_strings=["1"])])
sot.add_command("image list".split(),
[mock.Mock(option_strings=["2"])])
sot.add_command("image create".split(),
[mock.Mock(option_strings=["3"])])
sot.add_command("volume type create".split(),
[mock.Mock(option_strings=["4"])])
sot.add_command("volume type delete".split(),
[mock.Mock(option_strings=["5"])])
self.assertEqual("image volume", sot.get_commands())
result = sot.get_data()
self.assertEqual("image", result[0][0])
self.assertEqual("create delete list", result[0][1])
self.assertEqual("image_create", result[1][0])
self.assertEqual("3", result[1][1])
self.assertEqual("image_delete", result[2][0])
self.assertEqual("1", result[2][1])
self.assertEqual("image_list", result[3][0])
self.assertEqual("2", result[3][1])
def test_complete_dictionary_subcmd(): def test_complete_dictionary_subcmd(self):
sot = complete.CompleteDictionary() sot = complete.CompleteDictionary()
sot.add_command("image delete".split(), sot.add_command("image delete".split(),
[mock.Mock(option_strings=["1"])]) [mock.Mock(option_strings=["1"])])
sot.add_command("image list".split(), sot.add_command("image list".split(),
[mock.Mock(option_strings=["2"])]) [mock.Mock(option_strings=["2"])])
sot.add_command("image list better".split(), sot.add_command("image list better".split(),
[mock.Mock(option_strings=["3"])]) [mock.Mock(option_strings=["3"])])
assert "image" == sot.get_commands() self.assertEqual("image", sot.get_commands())
result = sot.get_data() result = sot.get_data()
assert "image" == result[0][0] self.assertEqual("image", result[0][0])
assert "delete list list_better" == result[0][1] self.assertEqual("delete list list_better", result[0][1])
assert "image_delete" == result[1][0] self.assertEqual("image_delete", result[1][0])
assert "1" == result[1][1] self.assertEqual("1", result[1][1])
assert "image_list" == result[2][0] self.assertEqual("image_list", result[2][0])
assert "2 better" == result[2][1] self.assertEqual("2 better", result[2][1])
assert "image_list_better" == result[3][0] self.assertEqual("image_list_better", result[3][0])
assert "3" == result[3][1] self.assertEqual("3", result[3][1])
class FakeStdout: class FakeStdout:
@ -78,96 +80,92 @@ class FakeStdout:
return result return result
def given_cmdo_data(): class TestCompletionAlternatives(base.TestBase):
cmdo = "image server"
data = [("image", "create"), def given_cmdo_data(self):
("image_create", "--eolus"), cmdo = "image server"
("server", "meta ssh"), data = [("image", "create"),
("server_meta_delete", "--wilson"), ("image_create", "--eolus"),
("server_ssh", "--sunlight")] ("server", "meta ssh"),
return cmdo, data ("server_meta_delete", "--wilson"),
("server_ssh", "--sunlight")]
return cmdo, data
def then_data(self, content):
self.assertIn(" cmds='image server'\n", content)
self.assertIn(" cmds_image='create'\n", content)
self.assertIn(" cmds_image_create='--eolus'\n", content)
self.assertIn(" cmds_server='meta ssh'\n", content)
self.assertIn(" cmds_server_meta_delete='--wilson'\n", content)
self.assertIn(" cmds_server_ssh='--sunlight'\n", content)
def test_complete_no_code(self):
output = FakeStdout()
sot = complete.CompleteNoCode("doesNotMatter", output)
sot.write(*self.given_cmdo_data())
self.then_data(output.content)
def test_complete_bash(self):
output = FakeStdout()
sot = complete.CompleteBash("openstack", output)
sot.write(*self.given_cmdo_data())
self.then_data(output.content)
self.assertIn("_openstack()\n", output.content[0])
self.assertIn("complete -F _openstack openstack\n", output.content[-1])
def test_complete_command_parser(self):
sot = complete.CompleteCommand(mock.Mock(), mock.Mock())
parser = sot.get_parser('nothing')
self.assertEqual("nothing", parser.prog)
self.assertEqual("print bash completion command\n ",
parser.description)
def then_data(content): class TestCompletionAction(base.TestBase):
assert " cmds='image server'\n" in content
assert " cmds_image='create'\n" in content
assert " cmds_image_create='--eolus'\n" in content
assert " cmds_server='meta ssh'\n" in content
assert " cmds_server_meta_delete='--wilson'\n" in content
assert " cmds_server_ssh='--sunlight'\n" in content
def given_complete_command(self):
cmd_mgr = commandmanager.CommandManager('cliff.tests')
app = application.App('testing', '1', cmd_mgr, stdout=FakeStdout())
sot = complete.CompleteCommand(app, mock.Mock())
cmd_mgr.add_command('complete', complete.CompleteCommand)
return sot, app, cmd_mgr
def test_complete_no_code(): def then_actions_equal(self, actions):
output = FakeStdout() optstr = ' '.join(opt for action in actions
sot = complete.CompleteNoCode("doesNotMatter", output) for opt in action.option_strings)
sot.write(*given_cmdo_data()) self.assertEqual('-h --help --name --shell', optstr)
then_data(output.content)
def test_complete_command_get_actions(self):
sot, app, cmd_mgr = self.given_complete_command()
app.interactive_mode = False
actions = sot.get_actions(["complete"])
self.then_actions_equal(actions)
def test_complete_bash(): def test_complete_command_get_actions_interactive(self):
output = FakeStdout() sot, app, cmd_mgr = self.given_complete_command()
sot = complete.CompleteBash("openstack", output) app.interactive_mode = True
sot.write(*given_cmdo_data()) actions = sot.get_actions(["complete"])
then_data(output.content) self.then_actions_equal(actions)
assert "_openstack()\n" in output.content[0]
assert "complete -F _openstack openstack\n" in output.content[-1]
def test_complete_command_take_action(self):
sot, app, cmd_mgr = self.given_complete_command()
parsed_args = mock.Mock()
parsed_args.name = "test_take"
parsed_args.shell = "bash"
content = app.stdout.content
self.assertEqual(0, sot.take_action(parsed_args))
self.assertIn("_test_take()\n", content[0])
self.assertIn("complete -F _test_take test_take\n", content[-1])
self.assertIn(" cmds='complete help'\n", content)
self.assertIn(" cmds_complete='-h --help --name --shell'\n", content)
self.assertIn(" cmds_help='-h --help'\n", content)
def test_complete_command_parser(): def test_complete_command_remove_dashes(self):
sot = complete.CompleteCommand(mock.Mock(), mock.Mock()) sot, app, cmd_mgr = self.given_complete_command()
parser = sot.get_parser('nothing') parsed_args = mock.Mock()
assert "nothing" == parser.prog parsed_args.name = "test-take"
assert "print bash completion command\n " == parser.description parsed_args.shell = "bash"
content = app.stdout.content
self.assertEqual(0, sot.take_action(parsed_args))
def given_complete_command(): self.assertIn("_test_take()\n", content[0])
cmd_mgr = commandmanager.CommandManager('cliff.tests') self.assertIn("complete -F _test_take test-take\n", content[-1])
app = application.App('testing', '1', cmd_mgr, stdout=FakeStdout())
sot = complete.CompleteCommand(app, mock.Mock())
cmd_mgr.add_command('complete', complete.CompleteCommand)
return sot, app, cmd_mgr
def then_actions_equal(actions):
optstr = ' '.join(opt for action in actions
for opt in action.option_strings)
assert '-h --help --name --shell' == optstr
def test_complete_command_get_actions():
sot, app, cmd_mgr = given_complete_command()
app.interactive_mode = False
actions = sot.get_actions(["complete"])
then_actions_equal(actions)
def test_complete_command_get_actions_interactive():
sot, app, cmd_mgr = given_complete_command()
app.interactive_mode = True
actions = sot.get_actions(["complete"])
then_actions_equal(actions)
def test_complete_command_take_action():
sot, app, cmd_mgr = given_complete_command()
parsed_args = mock.Mock()
parsed_args.name = "test_take"
parsed_args.shell = "bash"
content = app.stdout.content
assert 0 == sot.take_action(parsed_args)
assert "_test_take()\n" in content[0]
assert "complete -F _test_take test_take\n" in content[-1]
assert " cmds='complete help'\n" in content
assert " cmds_complete='-h --help --name --shell'\n" in content
assert " cmds_help='-h --help'\n" in content
def test_complete_command_remove_dashes():
sot, app, cmd_mgr = given_complete_command()
parsed_args = mock.Mock()
parsed_args.name = "test-take"
parsed_args.shell = "bash"
content = app.stdout.content
assert 0 == sot.take_action(parsed_args)
assert "_test_take()\n" in content[0]
assert "complete -F _test_take test-take\n" in content[-1]

View File

@ -13,73 +13,74 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import mock
import argparse import argparse
import unittest
import mock
import six import six
from cliff.formatters import commaseparated from cliff.formatters import commaseparated
from cliff.tests import test_columns from cliff.tests import test_columns
def test_commaseparated_list_formatter(): class TestCSVFormatter(unittest.TestCase):
sf = commaseparated.CSVLister()
c = ('a', 'b', 'c')
d1 = ('A', 'B', 'C')
d2 = ('D', 'E', 'F')
data = [d1, d2]
expected = 'a,b,c\nA,B,C\nD,E,F\n'
output = six.StringIO()
parsed_args = mock.Mock()
parsed_args.quote_mode = 'none'
sf.emit_list(c, data, output, parsed_args)
actual = output.getvalue()
assert expected == actual
def test_commaseparated_list_formatter(self):
sf = commaseparated.CSVLister()
c = ('a', 'b', 'c')
d1 = ('A', 'B', 'C')
d2 = ('D', 'E', 'F')
data = [d1, d2]
expected = 'a,b,c\nA,B,C\nD,E,F\n'
output = six.StringIO()
parsed_args = mock.Mock()
parsed_args.quote_mode = 'none'
sf.emit_list(c, data, output, parsed_args)
actual = output.getvalue()
self.assertEqual(expected, actual)
def test_commaseparated_list_formatter_quoted(): def test_commaseparated_list_formatter_quoted(self):
sf = commaseparated.CSVLister() sf = commaseparated.CSVLister()
c = ('a', 'b', 'c') c = ('a', 'b', 'c')
d1 = ('A', 'B', 'C') d1 = ('A', 'B', 'C')
d2 = ('D', 'E', 'F') d2 = ('D', 'E', 'F')
data = [d1, d2] data = [d1, d2]
expected = '"a","b","c"\n"A","B","C"\n"D","E","F"\n' expected = '"a","b","c"\n"A","B","C"\n"D","E","F"\n'
output = six.StringIO() output = six.StringIO()
# Parse arguments as if passed on the command-line # Parse arguments as if passed on the command-line
parser = argparse.ArgumentParser(description='Testing...') parser = argparse.ArgumentParser(description='Testing...')
sf.add_argument_group(parser) sf.add_argument_group(parser)
parsed_args = parser.parse_args(['--quote', 'all']) parsed_args = parser.parse_args(['--quote', 'all'])
sf.emit_list(c, data, output, parsed_args) sf.emit_list(c, data, output, parsed_args)
actual = output.getvalue() actual = output.getvalue()
assert expected == actual self.assertEqual(expected, actual)
def test_commaseparated_list_formatter_formattable_column(self):
sf = commaseparated.CSVLister()
c = ('a', 'b', 'c')
d1 = ('A', 'B', test_columns.FauxColumn(['the', 'value']))
data = [d1]
expected = 'a,b,c\nA,B,[\'the\'\\, \'value\']\n'
output = six.StringIO()
parsed_args = mock.Mock()
parsed_args.quote_mode = 'none'
sf.emit_list(c, data, output, parsed_args)
actual = output.getvalue()
self.assertEqual(expected, actual)
def test_commaseparated_list_formatter_formattable_column(): def test_commaseparated_list_formatter_unicode(self):
sf = commaseparated.CSVLister() sf = commaseparated.CSVLister()
c = ('a', 'b', 'c') c = (u'a', u'b', u'c')
d1 = ('A', 'B', test_columns.FauxColumn(['the', 'value'])) d1 = (u'A', u'B', u'C')
data = [d1] happy = u'高兴'
expected = 'a,b,c\nA,B,[\'the\'\\, \'value\']\n' d2 = (u'D', u'E', happy)
output = six.StringIO() data = [d1, d2]
parsed_args = mock.Mock() expected = u'a,b,c\nA,B,C\nD,E,%s\n' % happy
parsed_args.quote_mode = 'none' output = six.StringIO()
sf.emit_list(c, data, output, parsed_args) parsed_args = mock.Mock()
actual = output.getvalue() parsed_args.quote_mode = 'none'
assert expected == actual sf.emit_list(c, data, output, parsed_args)
actual = output.getvalue()
if six.PY2:
def test_commaseparated_list_formatter_unicode(): actual = actual.decode('utf-8')
sf = commaseparated.CSVLister() self.assertEqual(expected, actual)
c = (u'a', u'b', u'c')
d1 = (u'A', u'B', u'C')
happy = u'高兴'
d2 = (u'D', u'E', happy)
data = [d1, d2]
expected = u'a,b,c\nA,B,C\nD,E,%s\n' % happy
output = six.StringIO()
parsed_args = mock.Mock()
parsed_args.quote_mode = 'none'
sf.emit_list(c, data, output, parsed_args)
actual = output.getvalue()
if six.PY2:
actual = actual.decode('utf-8')
assert expected == actual

View File

@ -13,117 +13,117 @@
# under the License. # under the License.
import json import json
import six
from cliff.formatters import json_format from cliff.formatters import json_format
from cliff.tests import base
from cliff.tests import test_columns from cliff.tests import test_columns
import mock import mock
import six
def test_json_format_one(): class TestJSONFormatter(base.TestBase):
sf = json_format.JSONFormatter()
c = ('a', 'b', 'c', 'd')
d = ('A', 'B', 'C', '"escape me"')
expected = {
'a': 'A',
'b': 'B',
'c': 'C',
'd': '"escape me"'
}
args = mock.Mock()
sf.add_argument_group(args)
args.noindent = True def test_one(self):
output = six.StringIO() sf = json_format.JSONFormatter()
sf.emit_one(c, d, output, args) c = ('a', 'b', 'c', 'd')
value = output.getvalue() d = ('A', 'B', 'C', '"escape me"')
print(len(value.splitlines())) expected = {
assert 1 == len(value.splitlines()) 'a': 'A',
actual = json.loads(value) 'b': 'B',
assert expected == actual 'c': 'C',
'd': '"escape me"'
}
args = mock.Mock()
sf.add_argument_group(args)
args.noindent = False args.noindent = True
output = six.StringIO() output = six.StringIO()
sf.emit_one(c, d, output, args) sf.emit_one(c, d, output, args)
value = output.getvalue() value = output.getvalue()
assert 6 == len(value.splitlines()) print(len(value.splitlines()))
actual = json.loads(value) self.assertEqual(1, len(value.splitlines()))
assert expected == actual actual = json.loads(value)
self.assertEqual(expected, actual)
args.noindent = False
output = six.StringIO()
sf.emit_one(c, d, output, args)
value = output.getvalue()
self.assertEqual(6, len(value.splitlines()))
actual = json.loads(value)
self.assertEqual(expected, actual)
def test_json_format_formattablecolumn_one(): def test_formattablecolumn_one(self):
sf = json_format.JSONFormatter() sf = json_format.JSONFormatter()
c = ('a', 'b', 'c', 'd') c = ('a', 'b', 'c', 'd')
d = ('A', 'B', 'C', test_columns.FauxColumn(['the', 'value'])) d = ('A', 'B', 'C', test_columns.FauxColumn(['the', 'value']))
expected = { expected = {
'a': 'A', 'a': 'A',
'b': 'B', 'b': 'B',
'c': 'C', 'c': 'C',
'd': ['the', 'value'], 'd': ['the', 'value'],
} }
args = mock.Mock() args = mock.Mock()
sf.add_argument_group(args) sf.add_argument_group(args)
args.noindent = True args.noindent = True
output = six.StringIO() output = six.StringIO()
sf.emit_one(c, d, output, args) sf.emit_one(c, d, output, args)
value = output.getvalue() value = output.getvalue()
print(len(value.splitlines())) print(len(value.splitlines()))
assert 1 == len(value.splitlines()) self.assertEqual(1, len(value.splitlines()))
actual = json.loads(value) actual = json.loads(value)
assert expected == actual self.assertEqual(expected, actual)
def test_list(self):
sf = json_format.JSONFormatter()
c = ('a', 'b', 'c')
d = (
('A1', 'B1', 'C1'),
('A2', 'B2', 'C2'),
('A3', 'B3', 'C3')
)
expected = [
{'a': 'A1', 'b': 'B1', 'c': 'C1'},
{'a': 'A2', 'b': 'B2', 'c': 'C2'},
{'a': 'A3', 'b': 'B3', 'c': 'C3'}
]
args = mock.Mock()
sf.add_argument_group(args)
def test_json_format_list(): args.noindent = True
sf = json_format.JSONFormatter() output = six.StringIO()
c = ('a', 'b', 'c') sf.emit_list(c, d, output, args)
d = ( value = output.getvalue()
('A1', 'B1', 'C1'), self.assertEqual(1, len(value.splitlines()))
('A2', 'B2', 'C2'), actual = json.loads(value)
('A3', 'B3', 'C3') self.assertEqual(expected, actual)
)
expected = [
{'a': 'A1', 'b': 'B1', 'c': 'C1'},
{'a': 'A2', 'b': 'B2', 'c': 'C2'},
{'a': 'A3', 'b': 'B3', 'c': 'C3'}
]
args = mock.Mock()
sf.add_argument_group(args)
args.noindent = True args.noindent = False
output = six.StringIO() output = six.StringIO()
sf.emit_list(c, d, output, args) sf.emit_list(c, d, output, args)
value = output.getvalue() value = output.getvalue()
assert 1 == len(value.splitlines()) self.assertEqual(17, len(value.splitlines()))
actual = json.loads(value) actual = json.loads(value)
assert expected == actual self.assertEqual(expected, actual)
args.noindent = False def test_formattablecolumn_list(self):
output = six.StringIO() sf = json_format.JSONFormatter()
sf.emit_list(c, d, output, args) c = ('a', 'b', 'c')
value = output.getvalue() d = (
assert 17 == len(value.splitlines()) ('A1', 'B1', test_columns.FauxColumn(['the', 'value'])),
actual = json.loads(value) )
assert expected == actual expected = [
{'a': 'A1', 'b': 'B1', 'c': ['the', 'value']},
]
args = mock.Mock()
sf.add_argument_group(args)
args.noindent = True
def test_json_format_formattablecolumn_list(): output = six.StringIO()
sf = json_format.JSONFormatter() sf.emit_list(c, d, output, args)
c = ('a', 'b', 'c') value = output.getvalue()
d = ( self.assertEqual(1, len(value.splitlines()))
('A1', 'B1', test_columns.FauxColumn(['the', 'value'])), actual = json.loads(value)
) self.assertEqual(expected, actual)
expected = [
{'a': 'A1', 'b': 'B1', 'c': ['the', 'value']},
]
args = mock.Mock()
sf.add_argument_group(args)
args.noindent = True
output = six.StringIO()
sf.emit_list(c, d, output, args)
value = output.getvalue()
assert 1 == len(value.splitlines())
actual = json.loads(value)
assert expected == actual

View File

@ -16,81 +16,81 @@ import argparse
import six import six
from cliff.formatters import shell from cliff.formatters import shell
from cliff.tests import base
from cliff.tests import test_columns from cliff.tests import test_columns
import mock import mock
def test_shell_formatter(): class TestShellFormatter(base.TestBase):
sf = shell.ShellFormatter()
c = ('a', 'b', 'c', 'd')
d = ('A', 'B', 'C', '"escape me"')
expected = 'a="A"\nb="B"\nd="\\"escape me\\""\n'
output = six.StringIO()
args = mock.Mock()
args.variables = ['a', 'b', 'd']
args.prefix = ''
sf.emit_one(c, d, output, args)
actual = output.getvalue()
assert expected == actual
def test(self):
sf = shell.ShellFormatter()
c = ('a', 'b', 'c', 'd')
d = ('A', 'B', 'C', '"escape me"')
expected = 'a="A"\nb="B"\nd="\\"escape me\\""\n'
output = six.StringIO()
args = mock.Mock()
args.variables = ['a', 'b', 'd']
args.prefix = ''
sf.emit_one(c, d, output, args)
actual = output.getvalue()
self.assertEqual(expected, actual)
def test_shell_formatter_args(): def test_args(self):
sf = shell.ShellFormatter() sf = shell.ShellFormatter()
c = ('a', 'b', 'c', 'd') c = ('a', 'b', 'c', 'd')
d = ('A', 'B', 'C', '"escape me"') d = ('A', 'B', 'C', '"escape me"')
expected = 'Xd="\\"escape me\\""\n' expected = 'Xd="\\"escape me\\""\n'
output = six.StringIO() output = six.StringIO()
# Parse arguments as if passed on the command-line # Parse arguments as if passed on the command-line
parser = argparse.ArgumentParser(description='Testing...') parser = argparse.ArgumentParser(description='Testing...')
sf.add_argument_group(parser) sf.add_argument_group(parser)
parsed_args = parser.parse_args(['--variable', 'd', '--prefix', 'X']) parsed_args = parser.parse_args(['--variable', 'd', '--prefix', 'X'])
sf.emit_one(c, d, output, parsed_args) sf.emit_one(c, d, output, parsed_args)
actual = output.getvalue() actual = output.getvalue()
assert expected == actual self.assertEqual(expected, actual)
def test_formattable_column(self):
sf = shell.ShellFormatter()
c = ('a', 'b', 'c')
d = ('A', 'B', test_columns.FauxColumn(['the', 'value']))
expected = '\n'.join([
'a="A"',
'b="B"',
'c="[\'the\', \'value\']"\n',
])
output = six.StringIO()
args = mock.Mock()
args.variables = ['a', 'b', 'c']
args.prefix = ''
sf.emit_one(c, d, output, args)
actual = output.getvalue()
self.assertEqual(expected, actual)
def test_shell_formatter_formattable_column(): def test_non_string_values(self):
sf = shell.ShellFormatter() sf = shell.ShellFormatter()
c = ('a', 'b', 'c') c = ('a', 'b', 'c', 'd', 'e')
d = ('A', 'B', test_columns.FauxColumn(['the', 'value'])) d = (True, False, 100, '"esc"', six.text_type('"esc"'))
expected = '\n'.join([ expected = ('a="True"\nb="False"\nc="100"\n'
'a="A"', 'd="\\"esc\\""\ne="\\"esc\\""\n')
'b="B"', output = six.StringIO()
'c="[\'the\', \'value\']"\n', args = mock.Mock()
]) args.variables = ['a', 'b', 'c', 'd', 'e']
output = six.StringIO() args.prefix = ''
args = mock.Mock() sf.emit_one(c, d, output, args)
args.variables = ['a', 'b', 'c'] actual = output.getvalue()
args.prefix = '' self.assertEqual(expected, actual)
sf.emit_one(c, d, output, args)
actual = output.getvalue()
assert expected == actual
def test_non_bash_friendly_values(self):
def test_shell_formatter_with_non_string_values(): sf = shell.ShellFormatter()
sf = shell.ShellFormatter() c = ('a', 'foo-bar', 'provider:network_type')
c = ('a', 'b', 'c', 'd', 'e') d = (True, 'baz', 'vxlan')
d = (True, False, 100, '"esc"', six.text_type('"esc"')) expected = 'a="True"\nfoo_bar="baz"\nprovider_network_type="vxlan"\n'
expected = 'a="True"\nb="False"\nc="100"\nd="\\"esc\\""\ne="\\"esc\\""\n' output = six.StringIO()
output = six.StringIO() args = mock.Mock()
args = mock.Mock() args.variables = ['a', 'foo-bar', 'provider:network_type']
args.variables = ['a', 'b', 'c', 'd', 'e'] args.prefix = ''
args.prefix = '' sf.emit_one(c, d, output, args)
sf.emit_one(c, d, output, args) actual = output.getvalue()
actual = output.getvalue() self.assertEqual(expected, actual)
assert expected == actual
def test_shell_formatter_with_non_bash_friendly_values():
sf = shell.ShellFormatter()
c = ('a', 'foo-bar', 'provider:network_type')
d = (True, 'baz', 'vxlan')
expected = 'a="True"\nfoo_bar="baz"\nprovider_network_type="vxlan"\n'
output = six.StringIO()
args = mock.Mock()
args.variables = ['a', 'foo-bar', 'provider:network_type']
args.prefix = ''
sf.emit_one(c, d, output, args)
actual = output.getvalue()
assert expected == actual

File diff suppressed because it is too large Load Diff

View File

@ -15,51 +15,51 @@
import six import six
from cliff.formatters import value from cliff.formatters import value
from cliff.tests import base
from cliff.tests import test_columns from cliff.tests import test_columns
def test_value_formatter(): class TestValueFormatter(base.TestBase):
sf = value.ValueFormatter()
c = ('a', 'b', 'c', 'd')
d = ('A', 'B', 'C', '"no escape me"')
expected = 'A\nB\nC\n"no escape me"\n'
output = six.StringIO()
sf.emit_one(c, d, output, None)
actual = output.getvalue()
assert expected == actual
def test(self):
sf = value.ValueFormatter()
c = ('a', 'b', 'c', 'd')
d = ('A', 'B', 'C', '"no escape me"')
expected = 'A\nB\nC\n"no escape me"\n'
output = six.StringIO()
sf.emit_one(c, d, output, None)
actual = output.getvalue()
self.assertEqual(expected, actual)
def test_value_formatter_formattable_column(): def test_formattable_column(self):
sf = value.ValueFormatter() sf = value.ValueFormatter()
c = ('a', 'b', 'c', 'd') c = ('a', 'b', 'c', 'd')
d = ('A', 'B', 'C', test_columns.FauxColumn(['the', 'value'])) d = ('A', 'B', 'C', test_columns.FauxColumn(['the', 'value']))
expected = "A\nB\nC\n['the', 'value']\n" expected = "A\nB\nC\n['the', 'value']\n"
output = six.StringIO() output = six.StringIO()
sf.emit_one(c, d, output, None) sf.emit_one(c, d, output, None)
actual = output.getvalue() actual = output.getvalue()
assert expected == actual self.assertEqual(expected, actual)
def test_list_formatter(self):
sf = value.ValueFormatter()
c = ('a', 'b', 'c')
d1 = ('A', 'B', 'C')
d2 = ('D', 'E', 'F')
data = [d1, d2]
expected = 'A B C\nD E F\n'
output = six.StringIO()
sf.emit_list(c, data, output, None)
actual = output.getvalue()
self.assertEqual(expected, actual)
def test_value_list_formatter(): def test_list_formatter_formattable_column(self):
sf = value.ValueFormatter() sf = value.ValueFormatter()
c = ('a', 'b', 'c') c = ('a', 'b', 'c')
d1 = ('A', 'B', 'C') d1 = ('A', 'B', test_columns.FauxColumn(['the', 'value']))
d2 = ('D', 'E', 'F') data = [d1]
data = [d1, d2] expected = "A B ['the', 'value']\n"
expected = 'A B C\nD E F\n' output = six.StringIO()
output = six.StringIO() sf.emit_list(c, data, output, None)
sf.emit_list(c, data, output, None) actual = output.getvalue()
actual = output.getvalue() self.assertEqual(expected, actual)
assert expected == actual
def test_value_list_formatter_formattable_column():
sf = value.ValueFormatter()
c = ('a', 'b', 'c')
d1 = ('A', 'B', test_columns.FauxColumn(['the', 'value']))
data = [d1]
expected = "A B ['the', 'value']\n"
output = six.StringIO()
sf.emit_list(c, data, output, None)
actual = output.getvalue()
assert expected == actual

View File

@ -16,85 +16,85 @@ import six
import yaml import yaml
from cliff.formatters import yaml_format from cliff.formatters import yaml_format
from cliff.tests import base
from cliff.tests import test_columns from cliff.tests import test_columns
import mock import mock
def test_yaml_format_one(): class TestYAMLFormatter(base.TestBase):
sf = yaml_format.YAMLFormatter()
c = ('a', 'b', 'c', 'd')
d = ('A', 'B', 'C', '"escape me"')
expected = {
'a': 'A',
'b': 'B',
'c': 'C',
'd': '"escape me"'
}
output = six.StringIO()
args = mock.Mock()
sf.emit_one(c, d, output, args)
actual = yaml.safe_load(output.getvalue())
assert expected == actual
def test_format_one(self):
sf = yaml_format.YAMLFormatter()
c = ('a', 'b', 'c', 'd')
d = ('A', 'B', 'C', '"escape me"')
expected = {
'a': 'A',
'b': 'B',
'c': 'C',
'd': '"escape me"'
}
output = six.StringIO()
args = mock.Mock()
sf.emit_one(c, d, output, args)
actual = yaml.safe_load(output.getvalue())
self.assertEqual(expected, actual)
def test_yaml_format_formattablecolumn_one(): def test_formattablecolumn_one(self):
sf = yaml_format.YAMLFormatter() sf = yaml_format.YAMLFormatter()
c = ('a', 'b', 'c', 'd') c = ('a', 'b', 'c', 'd')
d = ('A', 'B', 'C', test_columns.FauxColumn(['the', 'value'])) d = ('A', 'B', 'C', test_columns.FauxColumn(['the', 'value']))
expected = { expected = {
'a': 'A', 'a': 'A',
'b': 'B', 'b': 'B',
'c': 'C', 'c': 'C',
'd': ['the', 'value'], 'd': ['the', 'value'],
} }
args = mock.Mock() args = mock.Mock()
sf.add_argument_group(args) sf.add_argument_group(args)
args.noindent = True args.noindent = True
output = six.StringIO() output = six.StringIO()
sf.emit_one(c, d, output, args) sf.emit_one(c, d, output, args)
value = output.getvalue() value = output.getvalue()
print(len(value.splitlines())) print(len(value.splitlines()))
actual = yaml.safe_load(output.getvalue()) actual = yaml.safe_load(output.getvalue())
assert expected == actual self.assertEqual(expected, actual)
def test_list(self):
sf = yaml_format.YAMLFormatter()
c = ('a', 'b', 'c')
d = (
('A1', 'B1', 'C1'),
('A2', 'B2', 'C2'),
('A3', 'B3', 'C3')
)
expected = [
{'a': 'A1', 'b': 'B1', 'c': 'C1'},
{'a': 'A2', 'b': 'B2', 'c': 'C2'},
{'a': 'A3', 'b': 'B3', 'c': 'C3'}
]
output = six.StringIO()
args = mock.Mock()
sf.add_argument_group(args)
sf.emit_list(c, d, output, args)
actual = yaml.safe_load(output.getvalue())
self.assertEqual(expected, actual)
def test_yaml_format_list(): def test_formattablecolumn_list(self):
sf = yaml_format.YAMLFormatter() sf = yaml_format.YAMLFormatter()
c = ('a', 'b', 'c') c = ('a', 'b', 'c')
d = ( d = (
('A1', 'B1', 'C1'), ('A1', 'B1', test_columns.FauxColumn(['the', 'value'])),
('A2', 'B2', 'C2'), )
('A3', 'B3', 'C3') expected = [
) {'a': 'A1', 'b': 'B1', 'c': ['the', 'value']},
expected = [ ]
{'a': 'A1', 'b': 'B1', 'c': 'C1'}, args = mock.Mock()
{'a': 'A2', 'b': 'B2', 'c': 'C2'}, sf.add_argument_group(args)
{'a': 'A3', 'b': 'B3', 'c': 'C3'}
]
output = six.StringIO()
args = mock.Mock()
sf.add_argument_group(args)
sf.emit_list(c, d, output, args)
actual = yaml.safe_load(output.getvalue())
assert expected == actual
args.noindent = True
def test_yaml_format_formattablecolumn_list(): output = six.StringIO()
sf = yaml_format.YAMLFormatter() sf.emit_list(c, d, output, args)
c = ('a', 'b', 'c') actual = yaml.safe_load(output.getvalue())
d = ( self.assertEqual(expected, actual)
('A1', 'B1', test_columns.FauxColumn(['the', 'value'])),
)
expected = [
{'a': 'A1', 'b': 'B1', 'c': ['the', 'value']},
]
args = mock.Mock()
sf.add_argument_group(args)
args.noindent = True
output = six.StringIO()
sf.emit_list(c, d, output, args)
actual = yaml.safe_load(output.getvalue())
assert expected == actual

View File

@ -22,159 +22,153 @@ import mock
from cliff import app as application from cliff import app as application
from cliff import commandmanager from cliff import commandmanager
from cliff import help from cliff import help
from cliff.tests import base
from cliff.tests import utils from cliff.tests import utils
def test_show_help_for_command(): class TestHelp(base.TestBase):
# FIXME(dhellmann): Are commands tied too closely to the app? Or
# do commands know too much about apps by using them to get to the
# command manager?
stdout = StringIO()
app = application.App('testing', '1',
utils.TestCommandManager(utils.TEST_NAMESPACE),
stdout=stdout)
app.NAME = 'test'
help_cmd = help.HelpCommand(app, mock.Mock())
parser = help_cmd.get_parser('test')
parsed_args = parser.parse_args(['one'])
try:
help_cmd.run(parsed_args)
except SystemExit:
pass
assert stdout.getvalue() == 'TestParser'
def test_show_help_for_command(self):
# FIXME(dhellmann): Are commands tied too closely to the app? Or
# do commands know too much about apps by using them to get to the
# command manager?
stdout = StringIO()
app = application.App('testing', '1',
utils.TestCommandManager(utils.TEST_NAMESPACE),
stdout=stdout)
app.NAME = 'test'
help_cmd = help.HelpCommand(app, mock.Mock())
parser = help_cmd.get_parser('test')
parsed_args = parser.parse_args(['one'])
try:
help_cmd.run(parsed_args)
except SystemExit:
pass
self.assertEqual('TestParser', stdout.getvalue())
def test_list_matching_commands(): def test_list_matching_commands(self):
# FIXME(dhellmann): Are commands tied too closely to the app? Or # FIXME(dhellmann): Are commands tied too closely to the app? Or
# do commands know too much about apps by using them to get to the # do commands know too much about apps by using them to get to the
# command manager? # command manager?
stdout = StringIO() stdout = StringIO()
app = application.App('testing', '1', app = application.App('testing', '1',
utils.TestCommandManager(utils.TEST_NAMESPACE), utils.TestCommandManager(utils.TEST_NAMESPACE),
stdout=stdout) stdout=stdout)
app.NAME = 'test' app.NAME = 'test'
help_cmd = help.HelpCommand(app, mock.Mock()) help_cmd = help.HelpCommand(app, mock.Mock())
parser = help_cmd.get_parser('test') parser = help_cmd.get_parser('test')
parsed_args = parser.parse_args(['t']) parsed_args = parser.parse_args(['t'])
try: try:
help_cmd.run(parsed_args) help_cmd.run(parsed_args)
except SystemExit: except SystemExit:
pass pass
help_output = stdout.getvalue() help_output = stdout.getvalue()
assert 'Command "t" matches:' in help_output self.assertIn('Command "t" matches:', help_output)
assert 'three word command\n two words\n' in help_output self.assertIn('three word command\n two words\n', help_output)
def test_list_matching_commands_no_match(self):
# FIXME(dhellmann): Are commands tied too closely to the app? Or
# do commands know too much about apps by using them to get to the
# command manager?
stdout = StringIO()
app = application.App('testing', '1',
utils.TestCommandManager(utils.TEST_NAMESPACE),
stdout=stdout)
app.NAME = 'test'
help_cmd = help.HelpCommand(app, mock.Mock())
parser = help_cmd.get_parser('test')
parsed_args = parser.parse_args(['z'])
self.assertRaises(
ValueError,
help_cmd.run,
parsed_args,
)
def test_list_matching_commands_no_match(): def test_show_help_for_help(self):
# FIXME(dhellmann): Are commands tied too closely to the app? Or # FIXME(dhellmann): Are commands tied too closely to the app? Or
# do commands know too much about apps by using them to get to the # do commands know too much about apps by using them to get to the
# command manager? # command manager?
stdout = StringIO() stdout = StringIO()
app = application.App('testing', '1', app = application.App('testing', '1',
utils.TestCommandManager(utils.TEST_NAMESPACE), utils.TestCommandManager(utils.TEST_NAMESPACE),
stdout=stdout) stdout=stdout)
app.NAME = 'test' app.NAME = 'test'
help_cmd = help.HelpCommand(app, mock.Mock()) app.options = mock.Mock()
parser = help_cmd.get_parser('test') help_cmd = help.HelpCommand(app, mock.Mock())
parsed_args = parser.parse_args(['z']) parser = help_cmd.get_parser('test')
try: parsed_args = parser.parse_args([])
help_cmd.run(parsed_args) try:
except SystemExit: help_cmd.run(parsed_args)
pass except SystemExit:
except ValueError: pass
pass help_text = stdout.getvalue()
else: basecommand = os.path.split(sys.argv[0])[1]
assert False, 'Should have seen a ValueError' self.assertIn('usage: %s [--version]' % basecommand, help_text)
self.assertIn('optional arguments:\n --version', help_text)
expected = (
' one Test command.\n'
' three word command Test command.\n'
)
self.assertIn(expected, help_text)
def test_list_deprecated_commands(self):
# FIXME(dhellmann): Are commands tied too closely to the app? Or
# do commands know too much about apps by using them to get to the
# command manager?
stdout = StringIO()
app = application.App('testing', '1',
utils.TestCommandManager(utils.TEST_NAMESPACE),
stdout=stdout)
app.NAME = 'test'
try:
app.run(['--help'])
except SystemExit:
pass
help_output = stdout.getvalue()
self.assertIn('two words', help_output)
self.assertIn('three word command', help_output)
self.assertNotIn('old cmd', help_output)
def test_show_help_for_help(): @mock.patch.object(commandmanager.EntryPointWrapper, 'load',
# FIXME(dhellmann): Are commands tied too closely to the app? Or side_effect=Exception('Could not load EntryPoint'))
# do commands know too much about apps by using them to get to the def test_show_help_with_ep_load_fail(self, mock_load):
# command manager? stdout = StringIO()
stdout = StringIO() app = application.App('testing', '1',
app = application.App('testing', '1', utils.TestCommandManager(utils.TEST_NAMESPACE),
utils.TestCommandManager(utils.TEST_NAMESPACE), stdout=stdout)
stdout=stdout) app.NAME = 'test'
app.NAME = 'test' app.options = mock.Mock()
app.options = mock.Mock() app.options.debug = False
help_cmd = help.HelpCommand(app, mock.Mock()) help_cmd = help.HelpCommand(app, mock.Mock())
parser = help_cmd.get_parser('test') parser = help_cmd.get_parser('test')
parsed_args = parser.parse_args([]) parsed_args = parser.parse_args([])
try: try:
help_cmd.run(parsed_args) help_cmd.run(parsed_args)
except SystemExit: except SystemExit:
pass pass
help_text = stdout.getvalue() help_output = stdout.getvalue()
basecommand = os.path.split(sys.argv[0])[1] self.assertIn('Commands:', help_output)
assert 'usage: %s [--version]' % basecommand in help_text self.assertIn('Could not load', help_output)
assert 'optional arguments:\n --version' in help_text self.assertNotIn('Exception: Could not load EntryPoint', help_output)
expected = (
' one Test command.\n'
' three word command Test command.\n'
)
assert expected in help_text
@mock.patch.object(commandmanager.EntryPointWrapper, 'load',
def test_list_deprecated_commands(): side_effect=Exception('Could not load EntryPoint'))
# FIXME(dhellmann): Are commands tied too closely to the app? Or def test_show_help_print_exc_with_ep_load_fail(self, mock_load):
# do commands know too much about apps by using them to get to the stdout = StringIO()
# command manager? app = application.App('testing', '1',
stdout = StringIO() utils.TestCommandManager(utils.TEST_NAMESPACE),
app = application.App('testing', '1', stdout=stdout)
utils.TestCommandManager(utils.TEST_NAMESPACE), app.NAME = 'test'
stdout=stdout) app.options = mock.Mock()
app.NAME = 'test' app.options.debug = True
try: help_cmd = help.HelpCommand(app, mock.Mock())
app.run(['--help']) parser = help_cmd.get_parser('test')
except SystemExit: parsed_args = parser.parse_args([])
pass try:
help_output = stdout.getvalue() help_cmd.run(parsed_args)
assert 'two words' in help_output except SystemExit:
assert 'three word command' in help_output pass
assert 'old cmd' not in help_output help_output = stdout.getvalue()
self.assertIn('Commands:', help_output)
self.assertIn('Could not load', help_output)
@mock.patch.object(commandmanager.EntryPointWrapper, 'load', self.assertIn('Exception: Could not load EntryPoint', help_output)
side_effect=Exception('Could not load EntryPoint'))
def test_show_help_with_ep_load_fail(mock_load):
stdout = StringIO()
app = application.App('testing', '1',
utils.TestCommandManager(utils.TEST_NAMESPACE),
stdout=stdout)
app.NAME = 'test'
app.options = mock.Mock()
app.options.debug = False
help_cmd = help.HelpCommand(app, mock.Mock())
parser = help_cmd.get_parser('test')
parsed_args = parser.parse_args([])
try:
help_cmd.run(parsed_args)
except SystemExit:
pass
help_output = stdout.getvalue()
assert 'Commands:' in help_output
assert 'Could not load' in help_output
assert 'Exception: Could not load EntryPoint' not in help_output
@mock.patch.object(commandmanager.EntryPointWrapper, 'load',
side_effect=Exception('Could not load EntryPoint'))
def test_show_help_print_exc_with_ep_load_fail(mock_load):
stdout = StringIO()
app = application.App('testing', '1',
utils.TestCommandManager(utils.TEST_NAMESPACE),
stdout=stdout)
app.NAME = 'test'
app.options = mock.Mock()
app.options.debug = True
help_cmd = help.HelpCommand(app, mock.Mock())
parser = help_cmd.get_parser('test')
parsed_args = parser.parse_args([])
try:
help_cmd.run(parsed_args)
except SystemExit:
pass
help_output = stdout.getvalue()
assert 'Commands:' in help_output
assert 'Could not load' in help_output
assert 'Exception: Could not load EntryPoint' in help_output

View File

@ -15,69 +15,65 @@
import cmd2 import cmd2
from cliff.interactive import InteractiveApp from cliff.interactive import InteractiveApp
from cliff.tests import base
class FakeApp(object): class FakeApp(object):
NAME = 'Fake' NAME = 'Fake'
def make_interactive_app(*command_names): class TestInteractive(base.TestBase):
fake_command_manager = [(x, None) for x in command_names]
return InteractiveApp(FakeApp, fake_command_manager,
stdin=None, stdout=None)
def make_interactive_app(self, *command_names):
fake_command_manager = [(x, None) for x in command_names]
return InteractiveApp(FakeApp, fake_command_manager,
stdin=None, stdout=None)
def _test_completenames(expecteds, prefix): def _test_completenames(self, expecteds, prefix):
app = make_interactive_app('hips', 'hippo', 'nonmatching') app = self.make_interactive_app('hips', 'hippo', 'nonmatching')
assert set(app.completenames(prefix)) == set(expecteds) self.assertEqual(set(app.completenames(prefix)), set(expecteds))
def test_cmd2_completenames(self):
# cmd2.Cmd define do_help method
self._test_completenames(['help'], 'he')
def test_cmd2_completenames(): def test_cliff_completenames(self):
# cmd2.Cmd define do_help method self._test_completenames(['hips', 'hippo'], 'hip')
_test_completenames(['help'], 'he')
def test_no_completenames(self):
self._test_completenames([], 'taz')
def test_cliff_completenames(): def test_both_completenames(self):
_test_completenames(['hips', 'hippo'], 'hip') # cmd2.Cmd define do_history method
# NOTE(dtroyer): Before release 0.7.0 do_hi was also defined so we need
# to account for that in the list of possible responses.
# Remove this check after cmd2 0.7.0 is the minimum
# requirement.
if hasattr(cmd2.Cmd, "do_hi"):
self._test_completenames(['hi', 'history', 'hips', 'hippo'], 'hi')
else:
self._test_completenames(['history', 'hips', 'hippo'], 'hi')
def _test_completedefault(self, expecteds, line, begidx):
command_names = set(['show file', 'show folder', 'show long',
'list all'])
app = self.make_interactive_app(*command_names)
observeds = app.completedefault(None, line, begidx, None)
self.assertEqual(set(expecteds), set(observeds))
self.assertTrue(
set([line[:begidx] + x for x in observeds]) <= command_names
)
def test_no_completenames(): def test_empty_text_completedefault(self):
_test_completenames([], 'taz') # line = 'show ' + begidx = 5 implies text = ''
self._test_completedefault(['file', 'folder', ' long'], 'show ', 5)
def test_nonempty_text_completedefault2(self):
# line = 'show f' + begidx = 6 implies text = 'f'
self._test_completedefault(['file', 'folder'], 'show f', 5)
def test_both_completenames(): def test_long_completedefault(self):
# cmd2.Cmd define do_history method self._test_completedefault(['long'], 'show ', 6)
# NOTE(dtroyer): Before release 0.7.0 do_hi was also defined so we need
# to account for that in the list of possible responses.
# Remove this check after cmd2 0.7.0 is the minimum
# requirement.
if hasattr(cmd2.Cmd, "do_hi"):
_test_completenames(['hi', 'history', 'hips', 'hippo'], 'hi')
else:
_test_completenames(['history', 'hips', 'hippo'], 'hi')
def test_no_completedefault(self):
def _test_completedefault(expecteds, line, begidx): self._test_completedefault([], 'taz ', 4)
command_names = set(['show file', 'show folder', 'show long', 'list all'])
app = make_interactive_app(*command_names)
observeds = app.completedefault(None, line, begidx, None)
assert set(observeds) == set(expecteds)
assert set([line[:begidx] + x for x in observeds]) <= command_names
def test_empty_text_completedefault():
# line = 'show ' + begidx = 5 implies text = ''
_test_completedefault(['file', 'folder', ' long'], 'show ', 5)
def test_nonempty_text_completedefault2():
# line = 'show f' + begidx = 6 implies text = 'f'
_test_completedefault(['file', 'folder'], 'show f', 5)
def test_long_completedefault():
_test_completedefault(['long'], 'show ', 6)
def test_no_completedefault():
_test_completedefault([], 'taz ', 4)

View File

@ -15,6 +15,7 @@
import weakref import weakref
from cliff import lister from cliff import lister
from cliff.tests import base
import mock import mock
@ -43,33 +44,33 @@ class ExerciseLister(lister.Lister):
) )
def test_formatter_args(): class TestLister(base.TestBase):
app = mock.Mock()
test_lister = ExerciseLister(app, [])
parsed_args = mock.Mock() def test_formatter_args(self):
parsed_args.columns = ('Col1', 'Col2') app = mock.Mock()
parsed_args.formatter = 'test' test_lister = ExerciseLister(app, [])
test_lister.run(parsed_args) parsed_args = mock.Mock()
f = test_lister._formatter_plugins['test'] parsed_args.columns = ('Col1', 'Col2')
assert len(f.args) == 1 parsed_args.formatter = 'test'
args = f.args[0]
assert args[0] == list(parsed_args.columns)
data = list(args[1])
assert data == [['a', 'A'], ['b', 'B']]
test_lister.run(parsed_args)
f = test_lister._formatter_plugins['test']
self.assertEqual(1, len(f.args))
args = f.args[0]
self.assertEqual(list(parsed_args.columns), args[0])
data = list(args[1])
self.assertEqual([['a', 'A'], ['b', 'B']], data)
def test_no_exist_column(): def test_no_exist_column(self):
test_lister = ExerciseLister(mock.Mock(), []) test_lister = ExerciseLister(mock.Mock(), [])
parsed_args = mock.Mock() parsed_args = mock.Mock()
parsed_args.columns = ('no_exist_column',) parsed_args.columns = ('no_exist_column',)
parsed_args.formatter = 'test' parsed_args.formatter = 'test'
with mock.patch.object(test_lister, 'take_action') as mock_take_action: with mock.patch.object(test_lister, 'take_action') as mock_take_action:
mock_take_action.return_value = (('Col1', 'Col2', 'Col3'), []) mock_take_action.return_value = (('Col1', 'Col2', 'Col3'), [])
try: self.assertRaises(
test_lister.run(parsed_args) ValueError,
except ValueError: test_lister.run,
pass parsed_args,
else: )
assert False, 'Should have had an exception'

View File

@ -15,6 +15,7 @@
import weakref import weakref
from cliff import show from cliff import show
from cliff.tests import base
import mock import mock
@ -43,42 +44,41 @@ class ExerciseShowOne(show.ShowOne):
) )
def test_formatter_args(): class TestShow(base.TestBase):
app = mock.Mock()
test_show = ExerciseShowOne(app, [])
parsed_args = mock.Mock() def test_formatter_args(self):
parsed_args.columns = ('Col1', 'Col2') app = mock.Mock()
parsed_args.formatter = 'test' test_show = ExerciseShowOne(app, [])
test_show.run(parsed_args) parsed_args = mock.Mock()
f = test_show._formatter_plugins['test'] parsed_args.columns = ('Col1', 'Col2')
assert len(f.args) == 1 parsed_args.formatter = 'test'
args = f.args[0]
assert args[0] == list(parsed_args.columns)
data = list(args[1])
assert data == [('a', 'A'), ('b', 'B')]
test_show.run(parsed_args)
f = test_show._formatter_plugins['test']
self.assertEqual(1, len(f.args))
args = f.args[0]
self.assertEqual(list(parsed_args.columns), args[0])
data = list(args[1])
self.assertEqual([('a', 'A'), ('b', 'B')], data)
def test_dict2columns(): def test_dict2columns(self):
app = mock.Mock() app = mock.Mock()
test_show = ExerciseShowOne(app, []) test_show = ExerciseShowOne(app, [])
d = {'a': 'A', 'b': 'B', 'c': 'C'} d = {'a': 'A', 'b': 'B', 'c': 'C'}
expected = [('a', 'b', 'c'), ('A', 'B', 'C')] expected = [('a', 'b', 'c'), ('A', 'B', 'C')]
actual = list(test_show.dict2columns(d)) actual = list(test_show.dict2columns(d))
assert expected == actual self.assertEqual(expected, actual)
def test_no_exist_column(self):
def test_no_exist_column(): test_show = ExerciseShowOne(mock.Mock(), [])
test_show = ExerciseShowOne(mock.Mock(), []) parsed_args = mock.Mock()
parsed_args = mock.Mock() parsed_args.columns = ('no_exist_column',)
parsed_args.columns = ('no_exist_column',) parsed_args.formatter = 'test'
parsed_args.formatter = 'test' with mock.patch.object(test_show, 'take_action') as mock_take_action:
with mock.patch.object(test_show, 'take_action') as mock_take_action: mock_take_action.return_value = (('Col1', 'Col2', 'Col3'), [])
mock_take_action.return_value = (('Col1', 'Col2', 'Col3'), []) self.assertRaises(
try: ValueError,
test_show.run(parsed_args) test_show.run,
except ValueError: parsed_args,
pass )
else:
assert False, 'Should have had an exception'

View File

@ -15,92 +15,91 @@
import argparse import argparse
import textwrap import textwrap
from nose.tools import assert_equals
from cliff import sphinxext from cliff import sphinxext
from cliff.tests import base
def test_empty_help(): class TestSphinxExtension(base.TestBase):
"""Handle positional and optional actions without help messages."""
parser = argparse.ArgumentParser(prog='hello-world', add_help=False)
parser.add_argument('name', action='store')
parser.add_argument('--language', dest='lang')
output = '\n'.join(sphinxext._format_parser(parser)) def test_empty_help(self):
assert_equals(textwrap.dedent(""" """Handle positional and optional actions without help messages."""
.. program:: hello-world parser = argparse.ArgumentParser(prog='hello-world', add_help=False)
.. code-block:: shell parser.add_argument('name', action='store')
parser.add_argument('--language', dest='lang')
hello-world [--language LANG] name output = '\n'.join(sphinxext._format_parser(parser))
self.assertEqual(textwrap.dedent("""
.. program:: hello-world
.. code-block:: shell
.. option:: --language <LANG> hello-world [--language LANG] name
.. option:: name .. option:: --language <LANG>
""").lstrip(), output)
.. option:: name
""").lstrip(), output)
def test_nonempty_help(self):
"""Handle positional and optional actions with help messages."""
parser = argparse.ArgumentParser(prog='hello-world', add_help=False)
parser.add_argument('name', help='user name')
parser.add_argument('--language', dest='lang',
help='greeting language')
output = '\n'.join(sphinxext._format_parser(parser))
self.assertEqual(textwrap.dedent("""
.. program:: hello-world
.. code-block:: shell
hello-world [--language LANG] name
.. option:: --language <LANG>
greeting language
.. option:: name
user name
""").lstrip(), output)
def test_flag(self):
"""Handle a boolean argparse action."""
parser = argparse.ArgumentParser(prog='hello-world', add_help=False)
parser.add_argument('name', help='user name')
parser.add_argument('--translate', action='store_true',
help='translate to local language')
output = '\n'.join(sphinxext._format_parser(parser))
self.assertEqual(textwrap.dedent("""
.. program:: hello-world
.. code-block:: shell
hello-world [--translate] name
.. option:: --translate
translate to local language
.. option:: name
user name
""").lstrip(), output)
def test_supressed(self):
"""Handle a supressed action."""
parser = argparse.ArgumentParser(prog='hello-world', add_help=False)
parser.add_argument('name', help='user name')
parser.add_argument('--variable', help=argparse.SUPPRESS)
output = '\n'.join(sphinxext._format_parser(parser))
self.assertEqual(textwrap.dedent("""
.. program:: hello-world
.. code-block:: shell
hello-world name
def test_nonempty_help(): .. option:: name
"""Handle positional and optional actions with help messages."""
parser = argparse.ArgumentParser(prog='hello-world', add_help=False)
parser.add_argument('name', help='user name')
parser.add_argument('--language', dest='lang', help='greeting language')
output = '\n'.join(sphinxext._format_parser(parser)) user name
assert_equals(textwrap.dedent(""" """).lstrip(), output)
.. program:: hello-world
.. code-block:: shell
hello-world [--language LANG] name
.. option:: --language <LANG>
greeting language
.. option:: name
user name
""").lstrip(), output)
def test_flag():
"""Handle a boolean argparse action."""
parser = argparse.ArgumentParser(prog='hello-world', add_help=False)
parser.add_argument('name', help='user name')
parser.add_argument('--translate', action='store_true',
help='translate to local language')
output = '\n'.join(sphinxext._format_parser(parser))
assert_equals(textwrap.dedent("""
.. program:: hello-world
.. code-block:: shell
hello-world [--translate] name
.. option:: --translate
translate to local language
.. option:: name
user name
""").lstrip(), output)
def test_supressed():
"""Handle a supressed action."""
parser = argparse.ArgumentParser(prog='hello-world', add_help=False)
parser.add_argument('name', help='user name')
parser.add_argument('--variable', help=argparse.SUPPRESS)
output = '\n'.join(sphinxext._format_parser(parser))
assert_equals(textwrap.dedent("""
.. program:: hello-world
.. code-block:: shell
hello-world name
.. option:: name
user name
""").lstrip(), output)

View File

@ -15,65 +15,63 @@
import os import os
import struct import struct
import sys import sys
import unittest
import mock import mock
import nose
from cliff import utils from cliff import utils
from cliff.tests import base
def test_utils_terminal_width(): class TestTerminalWidth(base.TestBase):
width = utils.terminal_width(sys.stdout)
# Results are specific to the execution environment, so only assert
# that no error is raised.
assert width is None or isinstance(width, int)
def test(self):
width = utils.terminal_width(sys.stdout)
# Results are specific to the execution environment, so only assert
# that no error is raised.
if width is not None:
self.assertIsInstance(width, int)
@mock.patch('cliff.utils.os') @unittest.skipIf(not hasattr(os, 'get_terminal_size'),
def test_utils_terminal_width_get_terminal_size(mock_os): 'only needed for python 3.3 onwards')
if not hasattr(os, 'get_terminal_size'): @mock.patch('cliff.utils.os')
raise nose.SkipTest('only needed for python 3.3 onwards') def test_get_terminal_size(self, mock_os):
ts = os.terminal_size((10, 5)) ts = os.terminal_size((10, 5))
mock_os.get_terminal_size.return_value = ts mock_os.get_terminal_size.return_value = ts
width = utils.terminal_width(sys.stdout) width = utils.terminal_width(sys.stdout)
assert width == 10 self.assertEqual(10, width)
mock_os.get_terminal_size.side_effect = OSError()
width = utils.terminal_width(sys.stdout)
self.assertIs(None, width)
mock_os.get_terminal_size.side_effect = OSError() @unittest.skipIf(hasattr(os, 'get_terminal_size'),
width = utils.terminal_width(sys.stdout) 'only needed for python 3.2 and before')
assert width is None @mock.patch('fcntl.ioctl')
def test_ioctl(self, mock_ioctl):
mock_ioctl.return_value = struct.pack('hhhh', 57, 101, 0, 0)
width = utils.terminal_width(sys.stdout)
self.assertEqual(101, width)
mock_ioctl.side_effect = IOError()
width = utils.terminal_width(sys.stdout)
self.assertIs(None, width)
@unittest.skipIf(hasattr(os, 'get_terminal_size'),
'only needed for python 3.2 and before')
@mock.patch('cliff.utils.ctypes')
@mock.patch('sys.platform', 'win32')
def test_windows(self, mock_ctypes):
mock_ctypes.create_string_buffer.return_value.raw = struct.pack(
'hhhhHhhhhhh', 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
mock_ctypes.windll.kernel32.GetStdHandle.return_value = -11
mock_ctypes.windll.kernel32.GetConsoleScreenBufferInfo.return_value = 1
@mock.patch('fcntl.ioctl') width = utils.terminal_width(sys.stdout)
def test_utils_terminal_width_ioctl(mock_ioctl): self.assertEqual(101, width)
if hasattr(os, 'get_terminal_size'):
raise nose.SkipTest('only needed for python 3.2 and before')
mock_ioctl.return_value = struct.pack('hhhh', 57, 101, 0, 0)
width = utils.terminal_width(sys.stdout)
assert width == 101
mock_ioctl.side_effect = IOError() mock_ctypes.windll.kernel32.GetConsoleScreenBufferInfo.return_value = 0
width = utils.terminal_width(sys.stdout)
assert width is None
width = utils.terminal_width(sys.stdout)
self.assertIs(None, width)
@mock.patch('cliff.utils.ctypes') width = utils.terminal_width('foo')
@mock.patch('sys.platform', 'win32') self.assertIs(None, width)
def test_utils_terminal_width_windows(mock_ctypes):
if hasattr(os, 'get_terminal_size'):
raise nose.SkipTest('only needed for python 3.2 and before')
mock_ctypes.create_string_buffer.return_value.raw = struct.pack(
'hhhhHhhhhhh', 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
mock_ctypes.windll.kernel32.GetStdHandle.return_value = -11
mock_ctypes.windll.kernel32.GetConsoleScreenBufferInfo.return_value = 1
width = utils.terminal_width(sys.stdout)
assert width == 101
mock_ctypes.windll.kernel32.GetConsoleScreenBufferInfo.return_value = 0
width = utils.terminal_width(sys.stdout)
assert width is None
width = utils.terminal_width('foo')
assert width is None

View File

@ -1,9 +1,15 @@
# The order of packages is significant, because pip processes them in the order # The order of packages is significant, because pip processes them in the order
# of appearance. Changing the order has an impact on the overall integration # of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later. # process, which may cause wedges in the gate later.
nose # LGPL
python-subunit>=0.0.18 # Apache-2.0/BSD
testrepository>=0.0.18 # Apache-2.0/BSD
testtools>=1.4.0 # MIT
mock>=2.0 # BSD mock>=2.0 # BSD
testscenarios>=0.4 # Apache-2.0/BSD
coverage>=4.0 # Apache-2.0 coverage>=4.0 # Apache-2.0
# this is required for the docs build jobs # this is required for the docs build jobs
sphinx>=1.5.1 # BSD sphinx>=1.5.1 # BSD
oslosphinx>=4.7.0 # Apache-2.0 oslosphinx>=4.7.0 # Apache-2.0

View File

@ -1,6 +1,6 @@
[tox] [tox]
minversion = 2.0 minversion = 2.0
envlist = py35,py27,pypy,pep8 envlist = py35,py27,pep8
[testenv] [testenv]
setenv = setenv =
@ -11,7 +11,9 @@ passenv =
ZUUL_CACHE_DIR ZUUL_CACHE_DIR
distribute = False distribute = False
install_command = {toxinidir}/tools/tox_install.sh {env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} {opts} {packages} install_command = {toxinidir}/tools/tox_install.sh {env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} {opts} {packages}
commands = nosetests -d --with-coverage --cover-inclusive --cover-package cliff [] commands =
python setup.py test --coverage --coverage-package-name=cliff --slowest --testr-args='{posargs}'
coverage report --show-missing
deps = -r{toxinidir}/test-requirements.txt deps = -r{toxinidir}/test-requirements.txt
[testenv:pep8] [testenv:pep8]