如何对命令行参数进行单元测试?

7 投票
3 回答
10334 浏览
提问于 2025-04-16 17:21

我正在尝试给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 个回答

1

我有类似的需求,因为我需要一种方法来为测试设置假的命令行参数。

我发现,在每个需要的测试中重写 sys.argv 对我来说是有效的。你提到的 unittest.main() 函数参数是用来进行单元测试的,而不是用来测试你想要测试的模块。

4

与其真的从命令行发送一个指令,不如假设 OptionParser 会正常工作,然后用输入值来初始化变量。如果你有这样的代码:

from optparse import OptionParser
parser = OptionParser()
parser.add_option("-t", "--tag", dest="tag", help="tag id")

那么可以尝试像从命令行输入一样给 tag 赋值,然后把这些值传递给你的测试类的 __init__ 方法。

11

为什么不在运行 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.argvunittest.main 至少需要一个 argv 元素来作为程序名称。所以避免使用 None,用 [sys.argv[0]] 是个不错的选择,因为这样它就会认为没有命令行参数。


附言:我刚注意到你最后一句话。如果是这样的话——那就不要使用命令行参数。你的“主”测试脚本应该直接使用 unittest 的 API 来加载模块的测试用例,想怎么定制就怎么定制。

撰写回答