将Python脚本参数传递给测试模块
我有几个测试模块,这些模块都是通过一个驱动脚本一起调用的,这个脚本可以接受各种参数。测试本身是用Python的unittest模块写的。
import optparse
import unittest
import sys
import os
from tests import testvalidator
from tests import testmodifier
from tests import testimporter
#modify the path so that the test modules under /tests have access to the project root
sys.path.insert(0, os.path.dirname(__file__))
def run(verbosity):
if verbosity == "0":
sys.stdout = open(os.devnull, 'w')
test_suite = unittest.TestSuite()
test_suite.addTest(unittest.TestLoader().loadTestsFromTestCase(testvalidator.TestValidator))
test_suite.addTest(unittest.TestLoader().loadTestsFromTestCase(testmodifier.TestModifier))
test_suite.addTest(unittest.TestLoader().loadTestsFromTestCase(testimporter.TestDataImporter))
unittest.TextTestRunner(verbosity=int(verbosity)).run(test_suite)
if __name__ == "__main__":
#a simple way to control output verbosity
parser = optparse.OptionParser()
parser.add_option("--verbosity", "--verbosity", dest="verbosity", default="0")
(options, args) = parser.parse_args()
run(options.verbosity)
我的问题是,在这些测试模块中,有些测试我想根据传给驱动的不同参数来跳过。我知道unittest提供了一些装饰器可以做到这一点,但我不太清楚怎么把这些信息传递给各个模块。例如,如果我有一个--skip-slow
的参数,我该怎么标记那些慢的测试,让它们被跳过呢?
谢谢你的时间。
3 个回答
0
这是我解决这个问题的方法。在我的模块底部,我放了这段代码,用来根据命令行参数中是否有 --slow
来设置一个全局变量:
if __name__ == "__main__":
try:
i = sys.argv.index("--slow")
run_slow_tests=True
del sys.argv[i]
except ValueError:
pass
unittest.main()
然后在那些运行会比较慢的测试函数开头,我加了这条语句。如果没有设置包含慢测试的标志,它会抛出一个 unittest.SkipTest() 异常。
if not run_slow_tests:
raise unittest.SkipTest('Slow test skipped, unless --slow given in sys.argv.')
这样,当我正常调用这个模块时,慢测试就会被跳过。
% python src/my_test.py -v
test_slow (__main__.Tests) ... skipped 'Slow test skipped, unless --slow given in sys.argv.'
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK (skipped=1)
而当我加上 --slow
参数时,这个模块里的慢测试就会运行:
% python src/my_test.py -v --slow
test_slow (__main__.Tests) ... ok
----------------------------------------------------------------------
Ran 1 test in 10.110s
OK
不过,不幸的是,这个方法在 Unittest的测试发现中并不奏效。
% python -m unittest discover src "*_test.py" --slow
usage: python -m unittest discover [-h] [-v] [-q] [--locals] [-f] [-c] [-b]
[-k TESTNAMEPATTERNS] [-s START]
[-p PATTERN] [-t TOP]
python -m unittest discover: error: unrecognized arguments: --slow
而且使用 @unittest.SkipUnless() 装饰器也不行。我猜这是因为这个装饰器在模块定义时就评估它的参数,而这个参数在模块运行时才会被设置为正确的值,时间上是晚了一点。
虽然这个方法不是完美的,但它让我可以在Python的标准库中工作。像这样的需求是一个很好的理由去采用更好的框架,比如 nose tests。不过对于我当前的项目,我更倾向于不安装任何外部模块。
2
其实我之前也在想这个问题,最后终于找到了答案。
主文件...
...
if __name__ == '__main__':
args = argparser()
from tests import *
...
然后在你的测试模块里,只需要这样做:
from __main__ import args
print args
我试了一下,效果很好。最棒的是,这个方法非常简单,根本不算什么黑科技。