1
0
Fork 0
wuttjamaican/tests/commands/test_base.py
Lance Edgar 005f43d14e Add basic command line framework
`wutta setup` is the only real sub/command yet, and it does nothing
2023-11-19 14:22:25 -06:00

182 lines
5 KiB
Python

# -*- coding: utf-8; -*-
import argparse
import sys
from unittest import TestCase
from unittest.mock import MagicMock, patch
from wuttjamaican.commands import base
class TestCommand(TestCase):
def test_base(self):
# base command is for 'wutta' and has a 'setup' subcommand
cmd = base.Command()
self.assertEqual(cmd.name, 'wutta')
self.assertIn('setup', cmd.subcommands)
def test_sorted_subcommands(self):
cmd = base.Command(subcommands={'foo': 'FooSubcommand',
'bar': 'BarSubcommand'})
srtd = cmd.sorted_subcommands()
self.assertEqual(srtd, ['BarSubcommand', 'FooSubcommand'])
def test_run_may_print_help(self):
class Hello(base.Subcommand):
name = 'hello'
cmd = base.Command(subcommands={'hello': Hello})
# first run is not "tested" per se but gives us some coverage.
# (this will *actually* print help, b/c no args specified)
try:
cmd.run()
except SystemExit:
pass
# from now on we mock the help
print_help = MagicMock()
cmd.print_help = print_help
# help is shown if no subcommand is given
try:
cmd.run()
except SystemExit:
pass
print_help.assert_called_once_with()
# help is shown if -h is given
print_help.reset_mock()
try:
cmd.run('-h')
except SystemExit:
pass
print_help.assert_called_once_with()
# help is shown if --help is given
print_help.reset_mock()
try:
cmd.run('--help')
except SystemExit:
pass
print_help.assert_called_once_with()
# help is shown if bad arg is given
print_help.reset_mock()
try:
cmd.run('--this-means-nothing')
except SystemExit:
pass
print_help.assert_called_once_with()
# help is shown if bad subcmd is given
print_help.reset_mock()
try:
cmd.run('make-sandwich')
except SystemExit:
pass
print_help.assert_called_once_with()
# main help is *not* shown if subcommand *and* -h are given
# (sub help is shown instead in that case)
print_help.reset_mock()
try:
cmd.run('hello', '-h')
except SystemExit:
pass
print_help.assert_not_called()
def test_run_invokes_subcommand(self):
class Hello(base.Subcommand):
name = 'hello'
def add_args(self):
self.parser.add_argument('--foo', action='store_true')
def run(self, args):
self.run_with(foo=args.foo)
run_with = Hello.run_with = MagicMock()
cmd = base.Command(subcommands={'hello': Hello})
# omit --foo in which case that is false by default
cmd.run('hello')
run_with.assert_called_once_with(foo=False)
# specify --foo in which case that is true
run_with.reset_mock()
cmd.run('hello', '--foo')
run_with.assert_called_once_with(foo=True)
class TestCommandArgumentParser(TestCase):
def test_parse_args(self):
kw = {
'prog': 'wutta',
'add_help': False,
# nb. this flag requires python 3.9
'exit_on_error': False,
}
# nb. examples below assume a command line like:
# bin/wutta foo --bar
# first here is what default parser does
parser = argparse.ArgumentParser(**kw)
parser.add_argument('subcommand', nargs='*')
try:
args = parser.parse_args(['foo', '--bar'])
except SystemExit:
# nb. parser was not happy, tried to exit process
args = None
else:
self.assertEqual(args.subcommand, ['foo', '--bar'])
self.assertFalse(hasattr(args, 'argv'))
# now here is was custom parser does
# (moves extras to argv for subcommand parser)
parser = base.CommandArgumentParser(**kw)
parser.add_argument('subcommand', nargs='*')
args = parser.parse_args(['foo', '--bar'])
self.assertEqual(args.subcommand, ['foo'])
self.assertEqual(args.argv, ['--bar'])
class TestSubcommand(TestCase):
def test_run(self):
cmd = base.Command()
subcmd = base.Subcommand(cmd)
# TODO: this doesn't really test anything per se, but at least
# gives us the coverage..
subcmd._run()
class TestMain(TestCase):
# nb. this doesn't test anything per se but gives coverage
def test_explicit_args(self):
try:
base.main('--help')
except SystemExit:
pass
def test_implicit_args(self):
def true_exit(*args):
sys.exit(*args)
with patch('wuttjamaican.commands.base.sys') as mocksys:
mocksys.argv = ['wutta', '--help']
mocksys.exit = true_exit
try:
base.main()
except SystemExit:
pass