Argparse 单元测试:禁止显示帮助消息

Posted

技术标签:

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

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

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

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

【问题讨论】:

【参考方案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 子类。

【讨论】:

以上是关于Argparse 单元测试:禁止显示帮助消息的主要内容,如果未能解决你的问题,请参考以下文章

如何在单元测试中使用 argparse 参数调用函数?

带有 argparse 的 Python 单元测试

用于argparse的python单元测试

如何在单元测试期间测试所需的 argparse 参数?

单元测试运行原理探究

单元测试运行原理探究