Подтвердить что ты не робот

Пропустить unittest тест без синтаксиса декоратора

У меня есть набор тестов, которые я загрузил с помощью TestLoader (из модуля unittest) loadTestsFromModule(), т.е.

suite = loader.loadTestsFromModule(module)

Это дает мне вполне полный список тестов, которые отлично работают. Моя проблема в том, что тестовая проводка, с которой я работаю, иногда требует пропустить определенные тесты на основе различных критериев. Я хочу сделать что-то вроде этого:

for test in suite:
    mark the test as 'to-skip' if it meets certain criteria

Обратите внимание, что я не могу просто удалить тест из списка тестов, потому что я хочу, чтобы unittest test runner фактически пропускал тесты, добавлял их к пропущенному счету и всему этому джазу.

Документация unittest предлагает использовать декораторы вокруг методов тестирования или классов. Поскольку я загружаю эти тесты из модуля и определяю их, чтобы пропустить их по критериям, не содержащимся в самих тестах, я не могу использовать декораторы. Есть ли способ, которым я могу перебирать каждый отдельный тест, а некоторые - как "пропустить" тест без прямого доступа к тестовому классу или методам в классе?

4b9b3361

Ответ 1

Использование unittest.TestCase.skipTest:

import unittest

class TestFoo(unittest.TestCase):
    def setUp(self): print('setup')
    def tearDown(self): print('teardown')
    def test_spam(self): pass
    def test_egg(self): pass
    def test_ham(self): pass

if __name__ == '__main__':
    import sys
    loader = unittest.loader.defaultTestLoader
    runner = unittest.TextTestRunner(verbosity=2)
    suite = loader.loadTestsFromModule(sys.modules['__main__'])
    for ts in suite:
        for t in ts:
            if t.id().endswith('am'): # To skip `test_spam` and `test_ham`
                setattr(t, 'setUp', lambda: t.skipTest('criteria'))
    runner.run(suite)

печатает

test_egg (__main__.TestFoo) ... setup
teardown
ok
test_ham (__main__.TestFoo) ... skipped 'criteria'
test_spam (__main__.TestFoo) ... skipped 'criteria'

----------------------------------------------------------------------
Ran 3 tests in 0.001s

OK (skipped=2)


----------------------------------------------------------------------
Ran 3 tests in 0.002s

OK (skipped=2)

UPDATE

Обновлен код для исправления setUp вместо метода тестирования. В противном случае для проверки будут выполняться методы setUp/tearDown.

Примечание

unittest.TestCase.skipTest (Пропуск теста) был введен в Python 2.7, 3.1. Таким образом, этот метод работает только в Python 2.7+, 3.1 +.

Ответ 2

Это немного взломать, но поскольку вам нужно только поднять unittest.SkipTest, вы можете пройти через свой пакет и изменить каждый тест, чтобы поднять его для вас, вместо того, чтобы запускать фактический тестовый код:

import unittest
from unittest import SkipTest

class MyTestCase(unittest.TestCase):
    def test_this_should_skip(self):
        pass

    def test_this_should_get_skipped_too(self):
        pass

def _skip_test(reason):
    raise SkipTest(reason)

if __name__ == '__main__':
    suite = unittest.TestLoader().loadTestsFromTestCase(MyTestCase)
    for test in suite:
        skipped_test_method = lambda: _skip_test("reason")
        setattr(test, test._testMethodName, skipped_test_method)
    unittest.TextTestRunner(verbosity=2).run(suite)

Когда я запускаю это, это результат, который я получаю:

test_this_should_get_skipped_too (__main__.MyTestCase) ... skipped 'reason'
test_this_should_skip (__main__.MyTestCase) ... skipped 'reason'

----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK (skipped=2)

Ответ 3

Некоторые наблюдения:

  • Тест - это вызываемый объект с методом __call__(result)
  • TestCase предоставляет интерфейс более высокого уровня, позволяющий методам тестирования генерировать исключение SkipTest для пропусков
  • Декораторы skip выполняют именно это
  • Пропущенные тесты записываются с помощью метода TestResult.addSkip(test, reason).

Итак, вам просто нужно заменить пропущенные тесты специальным тестом, который вызывает addSkip:

class Skipper(object):
    def __init__(self, test, reason):
        self.test = test
        self.reason = reason

    def __call__(self, result):
        result.addSkip(self.test, self.reason)

Ответ 4

Google привел меня сюда.

Я нашел самый простой способ сделать это, подняв исключение SkipTest, когда выполняются ваши критерии пропуска.

from unittest.case import SkipTest

def test_this_foo(self):
    if <skip conditsion>:
        raise SkipTest

И этот тест будет отмечен как пропущенный.