Argparse unit tests: Suppress the help message

前端 未结 3 1795
广开言路
广开言路 2020-12-19 17:17

I\'m writing test cases for argparse implementation. I intend to test \'-h\' feature. The following code does it. But it also outputs the usage for the script. Is there a wa

相关标签:
3条回答
  • 2020-12-19 17:28

    When testing for exception codes, use self.assertRaises() as a context manager; this gives you access to the raised exception, letting you test the .code attribute:

    with self.assertRaises(SystemExit) as cm:
        arg_parse_obj.parse_known_args(['-h'])
    
    self.assertEqual(cm.exception.code, 0)
    

    To 'suppress' or test the output, you'll have to capture either sys.stdout or sys.stderr, depending on the argparse output (help text goes to stdout). You could use a context manager for that:

    from contextlib import contextmanager
    from StringIO import StringIO
    
    @contextmanager
    def capture_sys_output():
        capture_out, capture_err = StringIO(), StringIO()
        current_out, current_err = sys.stdout, sys.stderr
        try:
            sys.stdout, sys.stderr = capture_out, capture_err
            yield capture_out, capture_err
        finally:
            sys.stdout, sys.stderr = current_out, current_err
    

    and use these as:

    with self.assertRaises(SystemExit) as cm:
        with capture_sys_output() as (stdout, stderr):
            arg_parse_obj.parse_known_args(['-h'])
    
    self.assertEqual(cm.exception.code, 0)
    
    self.assertEqual(stderr.getvalue(), '')
    self.assertEqual(stdout.getvalue(), 'Some help value printed')
    

    I nested the context managers here, but in Python 2.7 and newer you can also combine them into one line; this tends to get beyond the recommended 79 character limit in a hurry though.

    0 讨论(0)
  • 2020-12-19 17:34

    Some variations on using ['-h'] include:

    parser.print_help()  # formats the help, prints it and exits
    parser.format_help() # format the help without printing or exit
    parser.exit  # can be modified to not exit, such as for a parser subclass
    parser.error # default print usage and call parser.exit
    

    These are part of the public API.

    The argparse test file (test_argparse.py) also gives ideas on how to test things. For many tests it uses an ArgumentParser subclass that has its own error method.

    0 讨论(0)
  • 2020-12-19 17:42

    Mock could do this, allowing you the same functionality as Martijn Pieters' answer but without having to write your own function:

    from unittest.mock import MagicMock, patch
    
    argparse_mock = MagicMock()
    with patch('argparse.ArgumentParser._print_message', argparse_mock):
        with self.assertRaises(SystemExit) as cm:
            arg_parse_obj.parse_known_args(['-h'])
    

    patch also works as a decorator. If you have several instances where the argparse printing needs to be suppressed, you can do it as a decorator and avoid using a bunch of nested with statements.

    0 讨论(0)
提交回复
热议问题