Python 3.x 带有IP地址模块的Argparse单元测试

Python 3.x 带有IP地址模块的Argparse单元测试,python-3.x,argparse,python-unittest,python-mock,Python 3.x,Argparse,Python Unittest,Python Mock,我想为以下函数编写单元测试: #!/usr/bin/env python3 """IPv4 validation using `ipaddress module` and argparse.""" import argparse from ipaddress import ip_address def parse_cli_args(): """ Command line parser

我想为以下函数编写单元测试:

#!/usr/bin/env python3

"""IPv4 validation using `ipaddress module` and argparse."""

import argparse
from ipaddress import ip_address

def parse_cli_args():
    """
    Command line parser for subnet of interest.

    Args:
      --ip 0.0.0.0

    Returns:
      String, e.g. 0.0.0.0

    """

    parser = argparse.ArgumentParser(description="IPv4 address of interest.")
    parser.add_argument("--ip", action="store", type=ip_address,\
                        required=True,\
                        help="IP address of interest, e.g. 0.0.0.0")

    args = parser.parse_args()

    return args

if __name__ == '__main__':
    args = parse_cli_args()
    print(args.ip)
按预期工作,例如:

python3 test.py--ip 192.168.1.1

192.168.1.1

python3 test.py--ipderp

用法:test.py[-h]--ip test.py:错误:参数--ip:无效的ip_地址值:“derp”

python3 test.py--ip

用法:test.py[-h]--ip test.py:错误:参数--ip:应为一个参数

如何在单元测试中模拟这三个条件

我尝试了几种不同的方法:

import unittest
from unittest.mock import patch


class ParseCLIArgs(unittest.TestCase):

    """Unit tests."""

    @patch('builtins.input', return_value='192.168.1.1')
    def test_parse_cli_args_01(self, input):
        """Valid return value."""
        self.assertIsInstance(parse_cli_args(), ipaddress.IPv4Address)

if __name__ == '__main__':
    unittest.main()
没有成功。我做错了什么,我该如何纠正

编辑我进一步了解了这一点:

class ParseCLIArgs(unittest.TestCase):

def setUp(self):
    self.parser = parse_cli_args()

def test_parser_cli_args(self):
    parsed = self.parser.parse_args(['--ip', '192.168.1.1'])
    self.assertIs(parsed.ip, '192.168.1.1')

if __name__ == '__main__':
    unittest.main()

失败原因为:
TypeError:isinstance()arg 2必须是类型或类型的元组。我相信这是因为函数实际上转换了用户输入。

要测试解析器,您需要修改sys.argv
或提供自己的替代品

打电话时

 args = parser.parse_args(argv)
如果
argv
None
(或未提供),它将解析
sys.argv[1://code>。这是shell/解释器给出的列表。否则,它将解析您提供的等效列表

test_argparse.py
使用两种方法来测试解析器—构造自定义
sys.argv
并使用自定义
argv
调用
parse_args

另一件需要注意的事情是错误捕获。大多数解析错误显示用法、错误消息,然后退出。捕获该出口和stderr消息需要一些工作
test\u argparse
使用自定义的
error
方法生成
ArgumentParser
的子类


总之,对依赖于
sys.argv
的代码执行
unittest
,并退出系统,可能需要做更多的工作。也就是说,我不是单元测试和模拟工具方面的专家;我刚刚研究了
test\u argparse
文件。

要测试解析器,您需要修改
sys.argv
或提供自己的替代品

打电话时

 args = parser.parse_args(argv)
如果
argv
None
(或未提供),它将解析
sys.argv[1://code>。这是shell/解释器给出的列表。否则,它将解析您提供的等效列表

test_argparse.py
使用两种方法来测试解析器—构造自定义
sys.argv
并使用自定义
argv
调用
parse_args

另一件需要注意的事情是错误捕获。大多数解析错误显示用法、错误消息,然后退出。捕获该出口和stderr消息需要一些工作
test\u argparse
使用自定义的
error
方法生成
ArgumentParser
的子类


总之,对依赖于
sys.argv
的代码执行
unittest
,并退出系统,可能需要做更多的工作。也就是说,我不是单元测试和模拟工具方面的专家;我刚刚研究了
test\u argparse
文件。

希望这能为有类似问题的人提供很好的示例。这个测试完成了我希望它完成的大部分(但不是全部)。我还在做一个单元测试来检查
类型

#!/usr/bin/env python3

"""IPv4 validation using `ipaddress module` and argparse."""

import argparse
from ipaddress import ip_address

import unittest

def parse_cli_args():
    """
    Command line parser for subnet of interest.
    Args:
      --ip 0.0.0.0
    Returns:
      String, e.g. 0.0.0.0
    """

    parser = argparse.ArgumentParser(description="IPv4 address of interest.")
    parser.add_argument("--ip", action="store",\
                        required=True,\
                        help="IP address of interest, e.g. 0.0.0.0")

    return parser

class ParseCLIArgs(unittest.TestCase):

    def setUp(self):
        self.parser = parse_cli_args()

    def test_parser_cli_args(self):
        parsed = self.parser.parse_args(['--ip', '192.168.1.1'])
        self.assertEqual(parsed.ip, '192.168.1.1')



if __name__ == '__main__':
    unittest.main()

希望这能为有类似问题的人提供一个很好的例子。这个测试完成了我希望它完成的大部分(但不是全部)。我还在做一个单元测试来检查
类型

#!/usr/bin/env python3

"""IPv4 validation using `ipaddress module` and argparse."""

import argparse
from ipaddress import ip_address

import unittest

def parse_cli_args():
    """
    Command line parser for subnet of interest.
    Args:
      --ip 0.0.0.0
    Returns:
      String, e.g. 0.0.0.0
    """

    parser = argparse.ArgumentParser(description="IPv4 address of interest.")
    parser.add_argument("--ip", action="store",\
                        required=True,\
                        help="IP address of interest, e.g. 0.0.0.0")

    return parser

class ParseCLIArgs(unittest.TestCase):

    def setUp(self):
        self.parser = parse_cli_args()

    def test_parser_cli_args(self):
        parsed = self.parser.parse_args(['--ip', '192.168.1.1'])
        self.assertEqual(parsed.ip, '192.168.1.1')



if __name__ == '__main__':
    unittest.main()

在不详细阅读你的问题的情况下,我将作一般性的观察。测试框架通常有自己的解析器和命令行参数。因此,在上面添加您自己的论点可能很棘手。我不建议在测试框架中包含
argparse
。至于你的问题,它是不完整的。“未成功”是对您的问题的不充分描述。我想编写一个模拟有效用户输入的测试,例如
--ip 192.168.1.1
。提供的测试因以下错误而失败:
用法:test2.py[-h]--ip ip test2.py:错误:需要以下参数:--ip
,表明我实际上没有正确地传递模拟。在不详细阅读您的问题的情况下,我将进行一般性观察。测试框架通常有自己的解析器和命令行参数。因此,在上面添加您自己的论点可能很棘手。我不建议在测试框架中包含
argparse
。至于你的问题,它是不完整的。“未成功”是对您的问题的不充分描述。我想编写一个模拟有效用户输入的测试,例如
--ip 192.168.1.1
。提供的测试因以下错误而失败:
用法:test2.py[-h]--ip ip test2.py:错误:需要以下参数:--ip
,表示我实际上没有正确地传递模拟。我不清楚如何读取
test\u argparse
文件。我如何查看它呢?我曾经在开发发行版的
test
目录中找到过。它可能可以在当前的
github
存储库中找到,但我已经有一段时间没有查看了。这是一个复杂的文件,所以我不确定是否值得你研究一下。你用你的标签搜索过之前的SO了吗?我确实看了一个,尽管我认为我的用例有点不同,因为我调用了另一个模块来保证用户输入的准确性。我也是SO领域的爱好者……链接SO中的答案似乎涵盖了主要问题。我不清楚如何阅读
test\u argparse
文件。我如何查看它呢?我曾经在开发发行版的
test
目录中找到过。它可能可以在当前的
github
存储库中找到,但我已经有一段时间没有查看了。这是一个复杂的文件,所以我不确定是否值得你研究一下。你用你的标签搜索过以前的SO吗?我确实看了一个,尽管我认为我的用例很小