Модуль unittest: тестируем свои программы 2/2

Пропуск тестов и ожидаемые ошибки

unittest поддерживает пропуск отдельных тестов, а также классов тестов. Вдобавок, поддерживается пометка теста как "не работает, но так и надо".

Пропуск теста осуществляется использованием декоратораskip() или одного из его условных вариантов.

class MyTestCase(unittest.TestCase):

 @unittest.skip("demonstrating skipping")
 def test_nothing(self):
 self.fail("shouldn't happen")

 @unittest.skipIf(mylib.__version__ < (1, 3),
 "not supported in this library version")
 def test_format(self):
 # Tests that work for only a certain version of the library.
 pass

 @unittest.skipUnless(sys.platform.startswith("win"), "requires Windows")
 def test_windows_support(self):
 # windows specific testing code
 pass
test_format (__main__.MyTestCase) ... skipped 'not supported in this library version'
test_nothing (__main__.MyTestCase) ... skipped 'demonstrating skipping'
test_windows_support (__main__.MyTestCase) ... skipped 'requires Windows'

----------------------------------------------------------------------
Ran 3 tests in 0.005s

OK (skipped=3)

Классы также могут быть пропущены:

@unittest.skip("showing class skipping")
class MySkippedTestCase(unittest.TestCase):
 def test_not_run(self):
 pass

Ожмдаемые ошибки используют декоратор expectedFailure():

class ExpectedFailureTestCase(unittest.TestCase):
 @unittest.expectedFailure
 def test_fail(self):
 self.assertEqual(1, 0, "broken")

Очень просто сделать свой декоратор. Например, следующий декоратор пропускает тест, если переданный объект не имеет указанного атрибута:

def skipUnlessHasattr(obj, attr):
 if hasattr(obj, attr):
 return lambda func: func
 return unittest.skip("{!r} doesn't have {!r}".format(obj, attr))

Декораторы, пропускающие тесты или говорящие об ожидаемых ошибках:

@unittest.skip(reason) - пропустить тест. reason описывает причину пропуска.

@unittest.skipIf(condition, reason) - пропустить тест, если condition истинно.

@unittest.skipUnless(condition, reason) - пропустить тест, если condition ложно.

@unittest.expectedFailure - пометить тест как ожидаемая ошибка.

Для пропущенных тестов не запускаются setUp() и tearDown(). Для пропущенных классов не запускаются setUpClass() и tearDownClass(). Для пропущенных модулей не запускаются setUpModule() и tearDownModule().

Различение итераций теста с помощью подтестов

Когда некоторые тесты имеют лишь незначительные отличия, например некоторые параметры, unittest позволяет различать их внутри одного тестового метода, используяменеджер контекстаsubTest().

Например, следующий тест:

class NumbersTest(unittest.TestCase):

 def test_even(self):
 """
 Test that numbers between 0 and 5 are all even.
 """
 for i in range(0, 6):
 with self.subTest(i=i):
 self.assertEqual(i % 2, 0)

даст следующий отчёт:

======================================================================
FAIL: test_even (__main__.NumbersTest) (i=1)
----------------------------------------------------------------------
Traceback (most recent call last):
 File "subtests.py", line 32, in test_even
 self.assertEqual(i % 2, 0)
AssertionError: 1 != 0

======================================================================
FAIL: test_even (__main__.NumbersTest) (i=3)
----------------------------------------------------------------------
Traceback (most recent call last):
 File "subtests.py", line 32, in test_even
 self.assertEqual(i % 2, 0)
AssertionError: 1 != 0

======================================================================
FAIL: test_even (__main__.NumbersTest) (i=5)
----------------------------------------------------------------------
Traceback (most recent call last):
 File "subtests.py", line 32, in test_even
 self.assertEqual(i % 2, 0)
AssertionError: 1 != 0

Без использования подтестов, выполнение будет остановлено после первой ошибки, и ошибку будет сложнее диагностировать, потому что значение i не будет показано:

======================================================================
FAIL: test_even (__main__.NumbersTest)
----------------------------------------------------------------------
Traceback (most recent call last):
 File "subtests.py", line 32, in test_even
 self.assertEqual(i % 2, 0)
AssertionError: 1 != 0

Проверки на успешность

Модуль unittest предоставляет множество функций для самых различных проверок:

assertEqual(a, b) — a == b

assertNotEqual(a, b) — a != b

assertTrue(x) — bool(x) is True

assertFalse(x) — bool(x) is False

assertIs(a, b) — a is b

assertIsNot(a, b) — a is not b

assertIsNone(x) — x is None

assertIsNotNone(x) — x is not None

assertIn(a, b) — a in b

assertNotIn(a, b) — a not in b

assertIsInstance(a, b) — isinstance(a, b)

assertNotIsInstance(a, b) — not isinstance(a, b)

assertRaises(exc, fun, *args, **kwds) — fun(*args, **kwds) порождает исключение exc

assertRaisesRegex(exc, r, fun, *args, **kwds) — fun(*args, **kwds) порождает исключение exc и сообщение соответствует регулярному выражению r

assertWarns(warn, fun, *args, **kwds) — fun(*args, **kwds) порождает предупреждение

assertWarnsRegex(warn, r, fun, *args, **kwds) — fun(*args, **kwds) порождает предупреждение и сообщение соответствует регулярному выражению r

assertAlmostEqual(a, b) — round(a-b, 7) == 0

assertNotAlmostEqual(a, b) — round(a-b, 7) != 0

assertGreater(a, b) — a > b

assertGreaterEqual(a, b) — a >= b

assertLess(a, b) — a < b

assertLessEqual(a, b) — a <= b

assertRegex(s, r) — r.search(s)

assertNotRegex(s, r) — not r.search(s)

assertCountEqual(a, b) — a и b содержат те же элементы в одинаковых количествах, но порядок не важен

Категория: Python | Добавил: ghost_mod (08.04.2016)
Просмотров: 432 | Рейтинг: 0.0/0
Всего комментариев: 0
Имя *:
Email:
Подписка:1
Код *: