I'd like to write unit tests for the following function:
#!/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)
which works as expected, e.g.:
python3 test.py --ip 192.168.1.1
192.168.1.1
python3 test.py --ip derp
usage: test.py [-h] --ip IP test.py: error: argument --ip: invalid ip_address value: 'derp'
python3 test.py --ip
usage: test.py [-h] --ip IP test.py: error: argument --ip: expected one argument
How can I mock these three conditions in unit tests?
I tried a few variations of this:
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()
without success. What am I doing wrong, and how can I fix that?
EDIT I got a bit further with this:
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()
Which fails with: TypeError: isinstance() arg 2 must be a type or tuple of types
. I believe this is because the function actually transforms user input.