使用 unittest 发出模拟 argparse
Issue mocking argparse with unittest
我有需要测试的客户端代码
def arg_parser(arg_parse=None):
if not arg_parse:
arg_parse = sys.argv[1:]
parser = argparse.ArgumentParser()
parser.add_argument('--a', type=str, required=True)
parser.add_argument('--b', type=str, required=True)
return parser.parse_args(arg_parse)
def main():
arg_parse = arg_parser()
update_config(arg_parse)
......
def update_config(conf_args: argparse):
# read default YAML configuration file
with open('resources/config.yaml', 'r') as file:
conf = yaml.safe_load(file.read())
# Updated the YAML configuration file
if conf_args.a: // gives error here
..........
if __name__ == '__main__':
main()
我正在通过模拟 arg_parser 方法来测试这个主要方法
@mock.patch('test.prepare.arg_parser')
def test_main(mock_arg_parser):
args = arg_parser(['--a', 'a1',
'--b', 'b1'])
mock_arg_parser.return_value = args
...
main()
但是当我尝试从 argparse (arg_parse.a
)
访问参数时出现异常
# read default YAML configuration file
with open('resources/config.yaml', 'r') as file:
conf = yaml.safe_load(file.read())
# Updated the YAML configuration file
> if conf_args.a:
AttributeError: 'list' object has no attribute 'a'
不幸的是,我无法对齐客户端代码,因此需要修复测试。
所以事实证明您根本不需要涉及模拟——您可以按如下方式简化代码:
def arg_parser(argv):
parser = argparse.ArgumentParser()
parser.add_argument('--a', type=str, required=True)
parser.add_argument('--b', type=str, required=True)
return parser.parse_args(arg_parse)
def main(argv: Sequence[str] | None = None):
arg_parse = arg_parser(argv)
update_config(arg_parse)
......
def update_config(conf_args: argparse):
# read default YAML configuration file
with open('resources/config.yaml', 'r') as file:
conf = yaml.safe_load(file.read())
# Updated the YAML configuration file
if conf_args.a: # gives error here
..........
if __name__ == '__main__':
main()
然后在你的测试中显式地传递参数列表:
def test_main():
main(['--a', 'a1', '--b', 'b1'])
无需复杂的模拟!
这是可行的,因为 argparse.ArgumentParser.parse_args
在传递 None
时默认为 sys.argv[1:]
(默认情况下在您的脚本中发生),但您可以为测试传递测试参数!我复习了这个技巧 in a video I made
我有需要测试的客户端代码
def arg_parser(arg_parse=None):
if not arg_parse:
arg_parse = sys.argv[1:]
parser = argparse.ArgumentParser()
parser.add_argument('--a', type=str, required=True)
parser.add_argument('--b', type=str, required=True)
return parser.parse_args(arg_parse)
def main():
arg_parse = arg_parser()
update_config(arg_parse)
......
def update_config(conf_args: argparse):
# read default YAML configuration file
with open('resources/config.yaml', 'r') as file:
conf = yaml.safe_load(file.read())
# Updated the YAML configuration file
if conf_args.a: // gives error here
..........
if __name__ == '__main__':
main()
我正在通过模拟 arg_parser 方法来测试这个主要方法
@mock.patch('test.prepare.arg_parser')
def test_main(mock_arg_parser):
args = arg_parser(['--a', 'a1',
'--b', 'b1'])
mock_arg_parser.return_value = args
...
main()
但是当我尝试从 argparse (arg_parse.a
)
# read default YAML configuration file
with open('resources/config.yaml', 'r') as file:
conf = yaml.safe_load(file.read())
# Updated the YAML configuration file
> if conf_args.a:
AttributeError: 'list' object has no attribute 'a'
不幸的是,我无法对齐客户端代码,因此需要修复测试。
所以事实证明您根本不需要涉及模拟——您可以按如下方式简化代码:
def arg_parser(argv):
parser = argparse.ArgumentParser()
parser.add_argument('--a', type=str, required=True)
parser.add_argument('--b', type=str, required=True)
return parser.parse_args(arg_parse)
def main(argv: Sequence[str] | None = None):
arg_parse = arg_parser(argv)
update_config(arg_parse)
......
def update_config(conf_args: argparse):
# read default YAML configuration file
with open('resources/config.yaml', 'r') as file:
conf = yaml.safe_load(file.read())
# Updated the YAML configuration file
if conf_args.a: # gives error here
..........
if __name__ == '__main__':
main()
然后在你的测试中显式地传递参数列表:
def test_main():
main(['--a', 'a1', '--b', 'b1'])
无需复杂的模拟!
这是可行的,因为 argparse.ArgumentParser.parse_args
在传递 None
时默认为 sys.argv[1:]
(默认情况下在您的脚本中发生),但您可以为测试传递测试参数!我复习了这个技巧 in a video I made