你如何编写python模块的argparse部分的testing?
我有一个使用argparse库的Python模块。 如何为代码库的这一部分编写testing?
您应该重构您的代码并将parsing移到一个函数中:
def parse_args(args): parser = argparse.ArgumentParser(...) parser.add_argument... # ...Create your parser as you like... return parser.parse_args(args)
然后在你的main
function,你应该只是打电话给:
parser = parse_args(sys.argv[1:])
(代表脚本名称的sys.argv
的第一个元素在CLI操作期间被删除,不作为附加开关发送。
在你的testing中,你可以用你想要testing的任何参数列表来调用parsing器函数:
def test_parser(self): parser = parse_args(['-l', '-m']) self.assertTrue(parser.long) # ...and so on.
这样你就不必执行应用程序的代码来testingparsing器。
如果您稍后需要在应用程序中更改和/或向parsing器添加选项,请创build工厂方法:
def create_parser(): parser = argparse.ArgumentParser(...) parser.add_argument... # ...Create your parser as you like... return parser
如果你愿意的话,你可以稍后操作它,testing可能如下所示:
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部分”有点含糊,所以这个答案集中在一个部分: parse_args
方法。 这是与您的命令行交互并获取所有传递的值的方法。 基本上,你可以模拟什么parse_args
返回,以便它不需要从命令行实际获取值。
import argparse import mock @mock.patch('argparse.ArgumentParser.parse_args', return_value=argparse.Namespace(kwarg1=value, kwarg2=value)) def test_command(mock_args): pass
您必须将所有命令方法的参数包括在Namespace
即使它们没有通过。 给那些参数值None
。 (请参阅文档 )对于每个方法parameter passing不同值的情况,此样式对于快速进行testing非常有用。 如果您select在您的testing中模拟Namespace
本身,以确保它的行为与实际的Namespace
类相似。
- 使用
sys.argv.append()
填充你的arg列表,然后调用parse()
,检查结果并重复。 - 使用标志和转储参数标志调用批处理/ bash文件。
- 把所有的参数parsing到一个单独的文件,并在
if __name__ == "__main__":
调用parsing和转储/评估结果,然后从批处理/ bash文件中testing。
使你的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:]))
然后你可以正常testing。
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')
testingparsing器的简单方法是:
parser = ... parser.add_argument('-a',type=int) ... argv = '-a 1 foo'.split() # or ['-a','1','foo'] args = parser.parse_args(argv) assert(args.a == 1) ...
另一种方法是修改sys.argv
,并调用args = parser.parse_args()
在lib/test/test_argparse.py
有很多testingargparse
的例子
我发现,最简单的方法,至less我只是检查sys.argv [0],看看python是否运行python -m unittest
而不是parsing任何东西,如果是这样的话。
import sys import argparse parser = argparse.ArgumentParser() parser.add_argument('--outdir', help='Directory to output to', \ default='out') parser.add_argument('--file', help='Input file', \ default='section') parser.add_argument('--word', help='Word to look up') if sys.argv[0] == 'python -m unittest': args = parser.parse_args([]) else: args = parser.parse_args()