除非明确请求,否则禁用某些测试的自动测试执行

Jan*_*rny 6 python unit-testing nosetests

我有一些非常慢的测试和许多简短的单元测试。我希望能够使用简单的nosetests命令仅运行简短的单元测试,并且如果我决定是时候运行缓慢的测试,以便能够显式调用它们。

我希望能够做什么:

  • 运行单元测试但不运行缓慢的测试

    $ nosetests
    
    Run Code Online (Sandbox Code Playgroud)

    没有使用特殊的命令 - 任何出于nosetests好奇而进入的人都会在几秒钟内感到满意。

  • 明确请求慢速测试:

    $ nosetests --somehow-magicaly-invoke-slow-tests
    
    Run Code Online (Sandbox Code Playgroud)

    没有歧义 - 我想要慢速测试(或单元测试和慢速测试 - 这并不重要)

我尝试过什么:

我尝试使用nose.plugins.attrib

from nose.plugins.attrib import attr
import time

@attr('slow')
def test_slow_one():
    time.sleep(5)

def test_unittest():
    assert True
Run Code Online (Sandbox Code Playgroud)

但实际上它的作用几乎与我想要完成的目标相反 - 我必须指定额外的命令行参数才能不运行缓慢的测试。命令是:

运行单元测试,但不运行缓慢的测试

$ nosetests -v -a '!slow'
test_a.test_unittest ... ok
----------------------------------------------------------------------
Ran 1 test in 0.001s
OK
Run Code Online (Sandbox Code Playgroud)

明确请求慢速测试:

$ nosetests -v -a 'slow'
test_a.test_slow_one ... ok
----------------------------------------------------------------------
Ran 1 test in 5.005s
OK
Run Code Online (Sandbox Code Playgroud)

更糟糕的是,当有人跑步时

$ nosetests -v
test_a.test_slow_one ... ok
test_a.test_unittest ... ok
----------------------------------------------------------------------
Ran 2 tests in 5.007s
OK
Run Code Online (Sandbox Code Playgroud)

将运行所有测试,包括慢速测试。

问题:

有没有办法禁用某些测试,这样它们就不会用普通nosetests命令调用,但可以使用一些额外的命令行参数运行?

当前的“解决方案”:

我只是将所有缓慢的测试移至单独的文件中并命名这些文件,check_*.py而不是这样test_*.pynosetests不会选择它们。当我想运行缓慢的测试时,我只需指定文件的整个路径check_*.py,例如:

$ nosetests test/check_foo.py test/check_bar.py [...]
Run Code Online (Sandbox Code Playgroud)

这不是很优雅。

Luk*_*raf 4

您可以轻松地使用unittest.skipUnless()该效果。

跳过单个测试

只需装饰您想要有条件跳过的测试用例的方法

@unittest.skipUnless(condition, reason)
Run Code Online (Sandbox Code Playgroud)

例如,您可以检查您在自动化 CI 环境中未设置的环境变量,但设置是否以及何时要在本地运行慢速测试: SLOW_TESTS

import os
import time
import unittest


SLOW_TESTS = os.environ.get('SLOW_TESTS', False)


    class TestFoo(unittest.TestCase):

        def test_upper(self):
            self.assertEqual('foo'.upper(), 'FOO')

        @unittest.skipUnless(SLOW_TESTS, "slow test")
        def test_something_slow(self):
            time.sleep(5)
            self.assertTrue(True)
Run Code Online (Sandbox Code Playgroud)

常规运行的输出:

$ nosetests -v
test_something_slow (test_foo.TestFoo) ... SKIP: slow test
test_upper (test_foo.TestFoo) ... ok

----------------------------------------------------------------------
Ran 2 tests in 0.002s

OK (SKIP=1)
Run Code Online (Sandbox Code Playgroud)

设置环境变量时的输出:

$ SLOW_TESTS=1 nosetests -v
test_something_slow (test_foo.TestFoo) ... ok
test_upper (test_foo.TestFoo) ... ok

----------------------------------------------------------------------
Ran 2 tests in 5.003s

OK
Run Code Online (Sandbox Code Playgroud)

(请注意,Nose 测试运行程序仍然会说,Ran 2 tests即使它跳过了一个。跳过的测试在最后以 和(SKIP=n)在测试结果中以SKIPS在非详细模式指示)。

当然,您可以通过使用像在 CI 设置中设置的skipIf()环境变量来反转行为。FAST_TESTS

跳过整个测试用例

如果您想跳过TestCase 中已知速度较慢或设置繁重的所有TestCase.skipTest()测试,则显式调用可能会更方便(如果您需要更细粒度的控制,也可以从单个测试中执行此操作):

class TestFoo(unittest.TestCase):

    def setUp(self):
        if not SLOW_TESTS:
            self.skipTest("slow test")
        # some expensive setup
Run Code Online (Sandbox Code Playgroud)

有关跳过测试的更多详细信息,请参阅跳过测试和预期失败。