【问题标题】:Argparse unit tests: Suppress the help messageArgparse 单元测试:禁止显示帮助消息
【发布时间】:2013-09-10 04:41:43
【问题描述】:

我正在为 argparse 实现编写测试用例。我打算测试'-h'功能。下面的代码做到了。但它也输出脚本的用法。有没有办法抑制它?

self.assertRaises(SystemExit, arg_parse_obj.parse_known_args, ['-h'])

另外,我们可以检查抛出的异常号吗?例如 '-h' 抛出 SystemExit: 0,而无效或不足的 args 抛出 SystemExit: 2。有没有办法检查数字代码?

【问题讨论】:

    标签: python unit-testing argparse


    【解决方案1】:

    测试异常代码时,使用self.assertRaises() as a context manager;这使您可以访问引发的异常,让您测试.code 属性:

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

    要“抑制”或测试输出,您必须捕获sys.stdoutsys.stderr,具体取决于argparse 输出(帮助文本转到stdout)。您可以为此使用上下文管理器:

    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
    

    并将它们用作:

    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')
    

    我在这里嵌套了上下文管理器,但是在 Python 2.7 和更高版本中,您也可以将它们组合成一行;不过,这往往会很快超过建议的 79 个字符限制。

    【讨论】:

    • 哎呀,我认为with 将允许连续括号,但它没有,所以你不能做像with (really_long_expression as a, <NEWLINE>really_really_long_expression as b): suite 这样的事情。
    • 我讨厌使用反斜杠来继续。我希望将来他们会允许括号。我能看到的唯一问题是允许他们使用语法with (<expr>, <expr>, ...):(不使用as)将是模棱两可的,因为它可能意味着使用嵌套的上下文管理器,或者将元组本身用作上下文管理器(它不没有意义...)。
    • 我将此代码复制并粘贴到3.5stdout 是空的,而帮助消息打印在stderr
    • @raphael:默认情况下,帮助转到标准输出(请参阅print_help() function)。如果出现错误,则使用print_usage()given stdout as the output to write to
    • @MartijnPieters 啊,我的 b。我以您的代码为基础,但尝试测试错误并错过了区别
    【解决方案2】:

    Mock 可以做到这一点,允许您使用与 Martijn Pieters 的答案相同的功能,但无需编写自己的函数:

    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 也可以用作装饰器。如果您有多个需要抑制 argparse 打印的实例,您可以将其作为装饰器来执行,并避免使用一堆嵌套的 with 语句。

    【讨论】:

      【解决方案3】:

      使用['-h'] 的一些变化包括:

      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
      

      这些是公共 API 的一部分。

      argparse 测试文件 (test_argparse.py) 还提供了有关如何测试事物的想法。对于许多测试,它使用具有自己的error 方法的ArgumentParser 子类。

      【讨论】:

        猜你喜欢
        • 2015-07-26
        • 1970-01-01
        • 2014-01-25
        • 2016-06-21
        • 2012-08-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-16
        相关资源
        最近更新 更多