4

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

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

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

4

3 回答 3

17

测试异常代码时,self.assertRaises()用作上下文管理器;这使您可以访问引发的异常,让您测试.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 个字符限制。

于 2013-09-06T07:14:06.690 回答
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 语句。

于 2015-11-16T22:14:59.310 回答
0

使用的一些变化['-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) 还提供了有关如何测试事物的想法。对于许多测试,它使用ArgumentParser具有自己error方法的子类。

于 2013-09-06T16:00:17.137 回答