Commits

Andy Mikhailenko committed da29426

Okay, now 100% covered with tests. Of course there could be more tests but the library is just a thin wrapper around argparse which has lots of tests.

Comments (0)

Files changed (1)

 from argh import ArghParser, arg, add_commands, dispatch, plain_signature
 
 
+class DebugArghParser(ArghParser):
+    "(does not print stuff to stderr on exit)"
+
+    def exit(self, status=0, message=None):
+        raise SystemExit(message)
+
+    def error(self, message):
+        self.exit(2, message)
+
+
 @arg('text')
 def echo(args):
     return u'you said {0}'.format(args.text)
 
 class ArghTestCase(unittest.TestCase):
     def setUp(self):
-        #self.parser = build_parser(echo, foo=[hello, howdy])
-        self.parser = ArghParser()
+        #self.parser = build_parser(echo, plain_echo, foo=[hello, howdy])
+        self.parser = DebugArghParser('PROG')
         self.parser.add_commands([echo, plain_echo])
         self.parser.add_commands([hello, howdy], namespace='greet')
 
     def _call_cmd(self, command_string):
         args = command_string.split() if command_string else command_string
-        try:
-            return self.parser.dispatch(args)
-        except SystemExit:
-            self.fail('Argument parsing failed')
+        return self.parser.dispatch(args)
 
-    def assert_cmd_prints(self, command_string, expected_result):
+    def assert_cmd_returns(self, command_string, expected_result):
         """Executes given command using given parser and asserts that it prints
         given value.
         """
-        result = self._call_cmd(command_string)
+        try:
+            result = self._call_cmd(command_string)
+        except SystemExit:
+            self.fail('Argument parsing failed for {0}'.format(command_string))
         self.assertEqual(result, expected_result)
 
-    def assert_cmd_fails(self, command_string):
-        # TODO: suppress printing errors by the ArgumentParser
-        func = lambda: self.parser.dispatch(command_string.split())
-        self.assertRaises(SystemExit, func)
+    def assert_cmd_exits(self, command_string, message_regex=None):
+        "When a command forces exit, it *may* fail, but may just print help."
+        message_regex = str(message_regex)  # make sure None -> "None"
+        with self.assertRaisesRegexp(SystemExit, message_regex):
+            self.parser.dispatch(command_string.split())
+
+    def assert_cmd_fails(self, command_string, message_regex):
+        "exists with a message = fails"
+        self.assert_cmd_exits(command_string, message_regex)
+
+    def assert_cmd_doesnt_fail(self, command_string):
+        """(for cases when a commands doesn't fail but also (maybe) doesn't
+        return results and just prints them.)
+        """
+        result = self.assert_cmd_exits(command_string)
 
     def test_argv(self):
         _argv = sys.argv
         sys.argv = sys.argv[:1] + ['echo', 'hi there']
-        self.assert_cmd_prints(None, 'you said hi there')
+        self.assert_cmd_returns(None, 'you said hi there')
         sys.argv = _argv
 
+    def test_invalid_choice(self):
+        self.assert_cmd_fails('whatchamacallit', '^invalid choice')
+
     def test_echo(self):
         "A simple command is resolved to a function."
-        self.assert_cmd_prints('echo foo', 'you said foo')
+        self.assert_cmd_returns('echo foo', 'you said foo')
 
     def test_plain_signature(self):
         "Arguments can be passed to the function without a Namespace instance."
-        self.assert_cmd_prints('plain-echo bar', 'you said bar')
+        self.assert_cmd_returns('plain-echo bar', 'you said bar')
 
     def test_bare_namespace(self):
         "A command can be resolved to a function, to a namespace."
-        self.assert_cmd_fails('greet')
-        self.assert_cmd_fails('greet --name=world')
+        self.assert_cmd_fails('greet', 'too few arguments')
+        self.assert_cmd_fails('greet --name=world', 'too few arguments')
 
     def test_namespaced_function(self):
         "A subcommand is resolved to a function."
-        self.assert_cmd_prints('greet hello', u'Hello world!')
-        self.assert_cmd_prints('greet hello --name=John', u'Hello John!')
-        self.assert_cmd_fails('greet hello John')
-        self.assert_cmd_fails('greet howdy --name=John')
-        self.assert_cmd_prints('greet howdy John', u'Howdy John?')
+        self.assert_cmd_returns('greet hello', u'Hello world!')
+        self.assert_cmd_returns('greet hello --name=John', u'Hello John!')
+        self.assert_cmd_fails('greet hello John', 'unrecognized arguments')
+        self.assert_cmd_fails('greet howdy --name=John', 'too few arguments')
+        self.assert_cmd_returns('greet howdy John', u'Howdy John?')
 
-# TODO: find a workaround (it keeps printing to stdout)
-#    def test_help_alias(self):
-#        self._call_cmd('help echo')
-#        self.assertEqual(self._call_cmd('help echo'),
-#                         self._call_cmd('echo --help'))
+    def test_help_alias(self):
+        self.assert_cmd_doesnt_fail('--help')
+        self.assert_cmd_doesnt_fail('greet --help')
+        self.assert_cmd_doesnt_fail('greet hello --help')
+
+        self.assert_cmd_doesnt_fail('help')
+        self.assert_cmd_doesnt_fail('help greet')
+        self.assert_cmd_doesnt_fail('help greet hello')