检查 argparse.ArgumentTypeError

Check argparse.ArgumentTypeError

我想使用 pytest 检查 argparse.ArgumentTypeError 异常是否因参数不正确而引发:

import argparse
import os
import pytest


def main(argsIn):

    def configFile_validation(configFile):
        if not os.path.exists(configFile):
            msg = 'Configuration file "{}" not found!'.format(configFile)
            raise argparse.ArgumentTypeError(msg)
        return configFile

    parser = argparse.ArgumentParser()
    parser.add_argument('-c', '--configFile', help='Path to configuration file', dest='configFile', required=True, type=configFile_validation)
    args = parser.parse_args(argsIn)


def test_non_existing_config_file():
    with pytest.raises(argparse.ArgumentTypeError):
        main(['--configFile', 'non_existing_config_file.json'])

然而,运行 pytest 表示 During handling of the above exception, another exception occurred: 因此测试失败。我做错了什么?

问题是,如果参数的类型转换器引发异常 ArgumentTypeError agrparse exits,错误代码为 2,退出意味着引发内置异常 SystemExit。因此,您必须捕获该异常并验证原始异常的类型是否正确:

def test_non_existing_config_file():
    try:
        main(['--configFile', 'non_existing_config_file.json'])
    except SystemExit as e:
        assert isinstance(e.__context__, argparse.ArgumentError)
    else:
        raise ValueError("Exception not raised")

这是 test_argparse.py 文件中的 ArgumentTypeError 测试(在开发存储库中找到)

ErrorRaisingAgumentParser是定义在文件开头的子类,重新定义了parser.error方法,所以不退出,把错误信息放在stderr上。那部分有点复杂。

由于我在评论中描述的重定向,它无法直接测试 ArgumentTypeError。相反,它必须测试其消息。

# =======================
# ArgumentTypeError tests
# =======================

class TestArgumentTypeError(TestCase):

    def test_argument_type_error(self):

        def spam(string):
            raise argparse.ArgumentTypeError('spam!')

        parser = ErrorRaisingArgumentParser(prog='PROG', add_help=False)
        parser.add_argument('x', type=spam)
        with self.assertRaises(ArgumentParserError) as cm:
            parser.parse_args(['XXX'])
        self.assertEqual('usage: PROG x\nPROG: error: argument x: spam!\n',
                         cm.exception.stderr)

使用 pytest 您可以执行以下操作以检查是否引发了 argparse.ArugmentError。此外,您可以检查错误消息。

with pytest.raises(SystemExit) as e:
    main(['--configFile', 'non_existing_config_file.json'])

assert isinstance(e.value.__context__, argparse.ArgumentError)
assert 'expected err msg' in e.value.__context__.message