你如何编写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) 

然后在你的mainfunction,你应该只是打电话给:

 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类相似。

  1. 使用sys.argv.append()填充你的arg列表,然后调用parse() ,检查结果并重复。
  2. 使用标志和转储参数标志调用批处理/ bash文件。
  3. 把所有的参数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()