如何对命令行参数进行单元测试?
我正在尝试给Python的 unittest
提供命令行参数,但遇到了一些问题。
我在网上查找后发现了一种提供参数的方法,如下所示:
unittest.main(argv=[myArg])
这个方法对于单个命令行参数是有效的,但如果有多个参数就不行了。
unittest.main(argv=[myArg1, myArg2, myArg3])
上面的调用会出现以下错误:
File "/opt/python2.6.6/lib/python2.6/unittest.py", line 816, in __init__
self.parseArgs(argv)
File "/opt/python2.6.6/lib/python2.6/unittest.py", line 843, in parseArgs
self.createTests()
File "/opt/python2.6.6/lib/python2.6/unittest.py", line 849, in createTests
self.module)
File "/opt/python2.6.6/lib/python2.6/unittest.py", line 613, in
loadTestsFromNames suites = [self.loadTestsFromName(name, module)
for name in names]
File "/opt/python2.6.6/lib/python2.6/unittest.py", line 584, in
loadTestsFromName parent, obj = obj, getattr(obj, part)
AttributeError: 'module' object has no attribute 'admin'
我进一步研究发现,Python的 unittest
会把通过 argv
传入的所有内容都当作要运行的测试用例。
请告诉我是否还有其他方法可以给我的单元测试用例提供多个参数。我想覆盖一些硬编码的值,比如IP地址、测试用例标签等,并且希望从主测试脚本中运行这个测试脚本。
提前谢谢你。
3 个回答
我有类似的需求,因为我需要一种方法来为测试设置假的命令行参数。
我发现,在每个需要的测试中重写 sys.argv
对我来说是有效的。你提到的 unittest.main()
函数参数是用来进行单元测试的,而不是用来测试你想要测试的模块。
与其真的从命令行发送一个指令,不如假设 OptionParser
会正常工作,然后用输入值来初始化变量。如果你有这样的代码:
from optparse import OptionParser
parser = OptionParser()
parser.add_option("-t", "--tag", dest="tag", help="tag id")
那么可以尝试像从命令行输入一样给 tag
赋值,然后把这些值传递给你的测试类的 __init__
方法。
为什么不在运行 unittest.main
之前先把命令行参数拿出来,然后给它 [sys.argv[0]]
作为它的 argv
呢?
像这样:
if __name__ == '__main__':
# do stuff with sys.argv
unittest.main(argv=[sys.argv[0]])
需要注意的是,当给 argv=None
时,unittest.main
实际上会把这个当作信号,去解析 sys.argv
。unittest.main
至少需要一个 argv
元素来作为程序名称。所以避免使用 None
,用 [sys.argv[0]]
是个不错的选择,因为这样它就会认为没有命令行参数。
附言:我刚注意到你最后一句话。如果是这样的话——那就不要使用命令行参数。你的“主”测试脚本应该直接使用 unittest
的 API 来加载模块的测试用例,想怎么定制就怎么定制。