我有一个使用argparse库的Python模块。如何为这部分代码库编写测试?
当前回答
你应该重构你的代码,并将解析移动到一个函数:
def parse_args(args):
parser = argparse.ArgumentParser(...)
parser.add_argument...
# ...Create your parser as you like...
return parser.parse_args(args)
然后在你的main函数中,你只需调用它:
parser = parse_args(sys.argv[1:])
(其中sys. js的第一个元素。表示脚本名称的argv被删除,以便在CLI操作期间不将其作为额外的交换机发送。)
在你的测试中,你可以用你想要测试的参数列表来调用解析器函数:
def test_parser(self):
parser = parse_args(['-l', '-m'])
self.assertTrue(parser.long)
# ...and so on.
这样,您就不必为了测试解析器而执行应用程序的代码。
如果你以后需要在你的应用程序中更改和/或添加选项到你的解析器中,那么创建一个工厂方法:
def create_parser():
parser = argparse.ArgumentParser(...)
parser.add_argument...
# ...Create your parser as you like...
return parser
如果你愿意,你可以稍后对它进行操作,测试可以是这样的:
class ParserTest(unittest.TestCase):
def setUp(self):
self.parser = create_parser()
def test_something(self):
parsed = self.parser.parse_args(['--something', 'test'])
self.assertEqual(parsed.something, 'test')
其他回答
使你的main()函数接受argv作为参数,而不是让它从sys. .Argv,默认情况下:
# mymodule.py
import argparse
import sys
def main(args):
parser = argparse.ArgumentParser()
parser.add_argument('-a')
process(**vars(parser.parse_args(args)))
return 0
def process(a=None):
pass
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))
然后你就可以正常测试了。
import mock
from mymodule import main
@mock.patch('mymodule.process')
def test_main(process):
main([])
process.assert_call_once_with(a=None)
@mock.patch('foo.process')
def test_main_a(process):
main(['-a', '1'])
process.assert_call_once_with(a='1')
当从argparse.ArgumentParser传递结果时。parse_args函数,我有时使用namedtuple模拟参数进行测试。
import unittest
from collections import namedtuple
from my_module import main
class TestMyModule(TestCase):
args_tuple = namedtuple('args', 'arg1 arg2 arg3 arg4')
def test_arg1(self):
args = TestMyModule.args_tuple("age > 85", None, None, None)
res = main(args)
assert res == ["55289-0524", "00591-3496"], 'arg1 failed'
def test_arg2(self):
args = TestMyModule.args_tuple(None, [42, 69], None, None)
res = main(args)
assert res == [], 'arg2 failed'
if __name__ == '__main__':
unittest.main()
你应该重构你的代码,并将解析移动到一个函数:
def parse_args(args):
parser = argparse.ArgumentParser(...)
parser.add_argument...
# ...Create your parser as you like...
return parser.parse_args(args)
然后在你的main函数中,你只需调用它:
parser = parse_args(sys.argv[1:])
(其中sys. js的第一个元素。表示脚本名称的argv被删除,以便在CLI操作期间不将其作为额外的交换机发送。)
在你的测试中,你可以用你想要测试的参数列表来调用解析器函数:
def test_parser(self):
parser = parse_args(['-l', '-m'])
self.assertTrue(parser.long)
# ...and so on.
这样,您就不必为了测试解析器而执行应用程序的代码。
如果你以后需要在你的应用程序中更改和/或添加选项到你的解析器中,那么创建一个工厂方法:
def create_parser():
parser = argparse.ArgumentParser(...)
parser.add_argument...
# ...Create your parser as you like...
return parser
如果你愿意,你可以稍后对它进行操作,测试可以是这样的:
class ParserTest(unittest.TestCase):
def setUp(self):
self.parser = create_parser()
def test_something(self):
parsed = self.parser.parse_args(['--something', 'test'])
self.assertEqual(parsed.something, 'test')
我不想修改原来的服务脚本,所以我只是模拟出了系统。argparse中的Argv部分。
from unittest.mock import patch
with patch('argparse._sys.argv', ['python', 'serve.py']):
... # your test code here
如果argparse实现发生变化,这就会中断,但对于快速测试脚本来说已经足够了。在测试脚本中,敏感性要比特异性重要得多。
通过使用sys.argv.append()填充你的参数列表,然后调用 Parse(),检查结果并重复。 使用标记和dump args标记从批处理/bash文件调用。 将所有参数解析放在一个单独的文件中,并在if __name__ == "__main__":调用解析并转储/评估结果,然后从批处理/bash文件中测试。
推荐文章
- 使用python创建一个简单的XML文件
- APT命令行界面式的yes/no输入?
- 如何打印出状态栏和百分比?
- 单元测试:日期时间。现在
- 为什么单元测试中的代码不能找到包资源?
- 在Python中获取大文件的MD5哈希值
- 在Python格式字符串中%s是什么意思?
- 如何循环通过所有但最后一项的列表?
- python用什么方法避免默认参数为空列表?
- ValueError: numpy。Ndarray大小改变,可能表示二进制不兼容。期望从C头得到88,从PyObject得到80
- Anaconda /conda -安装特定的软件包版本
- 我在哪里调用Keras的BatchNormalization函数?
- 打印测试执行时间并使用py.test锁定缓慢的测试
- 插入一行到熊猫数据框架
- 要列出Pandas DataFrame列