传递Python脚本参数给测试模块

6

我有几个测试模块,都是通过一个驱动脚本一起调用的,该脚本可以接受各种参数。这些测试本身是使用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参数,那么我该如何注释慢速测试,并跳过它们呢?

感谢您的时间。


我可能找到了一个你可以使用的解决方案。请查看我的回答。 - John Doe
3个回答

2

你可以使用 nose 测试运行器和 attrib 插件,该插件允许您根据属性选择测试用例。特别地,插件文档中的示例使用 @attr(slow) 标记缓慢的测试用例。

之后,从命令行执行以下操作:

  • 选择所有标记为 slow 的测试用例:

    $ nosetests -a slow

  • 选择所有未标记为 slow 的测试用例:

    $ nosetests -a '!slow'


我可能需要熟悉一下nose,因为似乎unittest可能无法胜任这项任务。我一直希望不必添加依赖关系。 - zchtodd
1
你可以基于 unittest.skipIf/unittest.skipUnless 和一些环境变量来创建自己的 attr 装饰器,用于在跳过测试时检查条件。但是,当你已经有一个可以直接使用的工具时,我不认为这样做值得努力。 - jcollado

2

事实上,我自己也一直在思考这个问题,最终找到了解决方案。

主文件...

...
if __name__ == '__main__':
    args = argparser()

    from tests import *

    ...

在你的测试模块中,只需要执行以下操作:
from __main__ import args

print args

我测试了一下,效果非常好。最棒的是它非常简单,而且并不需要太多的技巧。

0
这是我解决这个问题的方法。在我的模块底部,我放置了以下代码来根据argv中是否存在--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)的好理由。对于我的当前项目,我更喜欢避免安装任何外部模块。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接