diff --git a/functional_tests/test_help.py b/functional_tests/test_help.py index af3874499df618bb89a14f909d77f4edff9b779a..56c1f45851d6411a124b45200fd8ab9b9123e915 100644 --- a/functional_tests/test_help.py +++ b/functional_tests/test_help.py @@ -43,3 +43,17 @@ def test_cli_works(): # be on the safe side. assert stderr == '' assert process.returncode == 0 + + +def test_usage_help_shown(): + # Since John feels a bit lazy, he decides to skip reading the + # documentation, and just run the tool to see if he gets any + # useful help. + process = subprocess.Popen(["gimmecert"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + stdout, stderr = process.communicate() + stdout, stderr = stdout.decode(), stderr.decode() + + # John is presented with short usage instructions. + assert "usage: gimmecert [-h]" in stdout + assert stderr == '' + assert process.returncode == 0 diff --git a/gimmecert/cli.py b/gimmecert/cli.py index bdd737297c6cbc4119e3c7e3addfbcb11b3752c0..2d69bc19ed103156795f77aa7f13206986415d7e 100644 --- a/gimmecert/cli.py +++ b/gimmecert/cli.py @@ -22,6 +22,12 @@ import argparse +DESCRIPTION = """\ +Issues server and client X.509 certificates using a local CA +hierarchy. +""" + + def get_parser(): """ Sets-up and returns a CLI argument parser. @@ -29,7 +35,9 @@ def get_parser(): :returns: argparse.ArgumentParser -- argument parser for CLI. """ - parser = argparse.ArgumentParser() + parser = argparse.ArgumentParser(description=DESCRIPTION) + + parser.set_defaults(func=lambda args: parser.print_usage()) return parser @@ -39,7 +47,13 @@ def main(): This function is a CLI entry point for the tool. It is a thin wrapper around the argument parser, and underlying command implementation. + + In order for this to work, the parser needs to register the + callback function as a default parameter for attribute + 'func'. This attribute is then invoked by the main function, + passing-in all the parsed arguments while at it. """ parser = get_parser() - parser.parse_args() + args = parser.parse_args() + args.func(args) diff --git a/setup.py b/setup.py index e4ba8bf86b5afa0dcbb7223b7696f6067daa4c62..01589d0d1a7c5dc3a831042012c20e911ecd48cf 100755 --- a/setup.py +++ b/setup.py @@ -73,7 +73,7 @@ setup( setup_requires=setup_requirements, tests_require=test_requirements, extras_require=extras_requirements, - entry_points = { + entry_points={ 'console_scripts': ['gimmecert=gimmecert.cli:main'], }, classifiers=[ diff --git a/tests/test_cli.py b/tests/test_cli.py index 217da74dd472459376a93afa866ac21e5d398bfa..14e4d3bc70d612e149ac35aa8d585a2f665cf0a8 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -48,3 +48,37 @@ def test_main_invokes_argument_parsing(mock_get_parser): gimmecert.cli.main() mock_parser.parse_args.assert_called_once_with() + + +def test_cli_parser_has_description(): + parser = gimmecert.cli.get_parser() + + assert parser.description + + +def test_parser_sets_up_default_callback_function(): + parser = gimmecert.cli.get_parser() + + assert callable(parser.get_default('func')) + + +@mock.patch('gimmecert.cli.argparse.ArgumentParser.print_usage') +def test_parser_default_callback_function_calls_print_usage(mock_print_usage): + parser = gimmecert.cli.get_parser() + func = parser.get_default('func') + func(mock.Mock()) + + assert mock_print_usage.called + + +@mock.patch('gimmecert.cli.get_parser') +def test_main_invokes_parser_function(mock_get_parser): + mock_parser = mock.Mock() + mock_args = mock.Mock() + + mock_parser.parse_args.return_value = mock_args + mock_get_parser.return_value = mock_parser + + gimmecert.cli.main() + + mock_args.func.assert_called_once_with(mock_args)