Пропустить 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 предлагает использовать декораторы вокруг методов тестирования или классов. Поскольку я загружаю эти тесты из модуля и определяю их, чтобы пропустить их по критериям, не содержащимся в самих тестах, я не могу использовать декораторы. Есть ли способ, которым я могу перебирать каждый отдельный тест, а некоторые - как "пропустить" тест без прямого доступа к тестовому классу или методам в классе?
Ответы
Ответ 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
И этот тест будет отмечен как пропущенный.