我想为以下函数编写单元测试:
#!/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 --ip derp
用法:test.py [-h]--IPIP test.py:错误:参数 --ip:无效ip_address值:"derp">
python3 test.py --ip
用法:test.py [-h] --IP IPtest.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 must be a type or tuple of types
。我相信这是因为该函数实际上转换了用户输入。
要测试解析器,您需要修改sys.argv
或提供自己的替代品。
当调用时
args = parser.parse_args(argv)
如果argv
None
(或未提供),则解析sys.argv[1:]
。 这是外壳/解释器给出的列表。 否则,它将解析您提供的等效列表。
test_argparse.py
使用两种方法来测试解析器 - 构造自定义sys.argv
并使用自定义argv
调用parse_args
。
需要注意的另一件事是错误捕获。 大多数解析错误显示使用情况、错误消息,然后退出。 捕获该出口和 stderr 消息需要一些工作。test_argparse
使用自定义error
方法创建ArgumentParser
子类。
总之,对依赖于sys.argv
的代码执行unittest
并执行系统退出,可能需要比其价值更多的工作。 也就是说,我不是单元测试和模拟工具方面的专家;我刚刚研究了test_argparse
文件。
希望这可以作为有类似问题的人的好样本。这个测试完成了我希望它做的大部分(但不是全部)事情。我仍在进行单元测试以检查Type
.
#!/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()