Как я могу украсить метод unittest Python, чтобы пропустить, если свойство, которое я ранее оценил, не является True?
Я пишу TestCase в Python, используя unittest, который выглядит примерно так:
class MyTestCase(unittest.TestCase):
def setUp(self):
# ... check if I'm online - might result in True or False
self.isOnline = True
@unittest.skipIf(not self.isOnline, "Not online")
def test_xyz(self):
# do a test that relies on being online
Однако это не работает, я полагаю, потому что @skipIf
не может использовать self
вне тела объявления функции. Я знаю, что могу проверить значение self.isOnline
внутри функции test_xyz
и использовать skipTest
вместо этого, но это менее элегантно. Есть ли другие варианты?
Ответы
Ответ 1
Вы можете написать свой собственный декоратор, которому вы передадите имя флага:
def skipIfTrue(flag):
def deco(f):
def wrapper(self, *args, **kwargs):
if getattr(self, flag):
self.skipTest()
else:
f(self, *args, **kwargs)
return wrapper
return deco
Затем в вашем классе вы определяете метод теста следующим образом:
@skipIfTrue('isOnline')
def test_thing(self):
print("A test")
Является ли это лучше, чем просто проверка метода зависит от ситуации. Если вы делаете это со многими методами, это может быть лучше, чем писать чек в каждом. С другой стороны, если вы это делаете, вы можете сгруппировать их вместе и сделать одну проверку, чтобы пропустить весь пакет.
Ответ 2
Если вы можете переместить тест isOnline
вне вашего метода setUp
, то это решение:
IS_ONLINE = i_am_online()
class MyTestCase(unittest.TestCase):
@unittest.skipUnless(IS_ONLINE, "Not online")
def test_xyz(self):
# do a test that relies on being online
Другой (более элегантный вариант):
import unittest
def skipWhenOffline():
if not i_am_online():
return unittest.skip("Not online")
return unittest._id
class MyTestCase(unittest.TestCase):
@unittest.skipWhenOffline()
def test_xyz(self):
# do a test that relies on being online
Однако, если это невозможно для вас, тогда нет более элегантного решения, чем каким-то образом использовать skipTest()
.
skipIf
и skipUnless
оцениваются во время объявления класса (они устанавливают атрибут __unittest_skip__
в вашем методе, чтобы указать, что он не должен запускаться, который позже просматривается до запуска теста). Ваш метод setUp
просто еще не запущен в этой точке.
Ответ 3
Я бы добавил к ответу BrenBarn, что если вы используете nosetests
, вам нужно украсить функцию wrapper
@wraps
. Без этого тестовая функция технически будет wrapper
, и это не будет вызываться nosetests
, так как по умолчанию методы тестирования должны начинаться с test_
.
from unittest2.compatibility import wraps
def skipIfTrue(flag):
def deco(f):
@wraps(f)
def wrapper(self, *args, **kwargs):
if getattr(self, flag):
self.skipTest()
else:
f(self, *args, **kwargs)
return wrapper
return deco
Ответ 4
Все остальные ответы здесь могут работать, но они более или менее взломаны и/или нуждаются в сторонних решениях.
Можно также пойти по старому пути, просто поставив if condition: self.skipTest()
в качестве первой строки в вашей тестовой функции.
def test_xyz(self):
if not self.isOnline:
self.skipTest("Not online")
## You could even write it as a one-liner, should you prefer
# if not self.isOnline: self.skipTest("Not online")
## Which happens to be exact the same length as the decorator,
## so it is roughtly the same as decorator even from the convenience standpoint
# @unittest.skipIf(not self.isOnline, "Not online")
do_a_test_that_relies_on_being_online(...)