我有一个使用argparse库的Python模块。如何为这部分代码库编写测试?


当前回答

当从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()

其他回答

当从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()

通过使用sys.argv.append()填充你的参数列表,然后调用 Parse(),检查结果并重复。 使用标记和dump args标记从批处理/bash文件调用。 将所有参数解析放在一个单独的文件中,并在if __name__ == "__main__":调用解析并转储/评估结果,然后从批处理/bash文件中测试。

我不想修改原来的服务脚本,所以我只是模拟出了系统。argparse中的Argv部分。

from unittest.mock import patch

with patch('argparse._sys.argv', ['python', 'serve.py']):
    ...  # your test code here

如果argparse实现发生变化,这就会中断,但对于快速测试脚本来说已经足够了。在测试脚本中,敏感性要比特异性重要得多。

使你的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')

测试解析器的一个简单方法是:

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. conf。然后调用args = parser.parse_args()

在lib/test/test_argparse.py中有很多测试argparse的例子