Ключевые assert-методы
Главные assert-методы TestCase и когда каждый из них уместен.
Assert-метод — метод
TestCase, который проверяет одно условие и роняет тест с понятным сообщением, если условие не выполнено.
Почему не просто assert
Можно писать assert a == b, но методы TestCase дают лучшую диагностику: вместо сухого «AssertionError» вы видите оба значения. assertEqual(2, 3) напечатает 2 != 3, а голый assert 2 == 3 — ничего полезного.
Самые ходовые методы
| Метод | Проходит, если |
assertEqual(a, b) | a == b |
assertNotEqual(a, b) | a != b |
assertTrue(x) | bool(x) истинно |
assertFalse(x) | bool(x) ложно |
assertIn(a, b) | a in b |
assertIsNone(x) | x is None |
assertAlmostEqual(a, b) | a и b близки (для float) |
assertRaises(Err) | вызов поднял исключение Err |
Запускаемый пример с разными методами
import unittest
def normalize(name):
return name.strip().lower()
class TestAsserts(unittest.TestCase):
def test_equal(self):
self.assertEqual(normalize(" Анна "), "анна")
def test_truthy(self):
self.assertTrue("анна") # непустая строка истинна
self.assertFalse("") # пустая строка ложна
def test_membership(self):
self.assertIn("a", "anna")
self.assertNotIn("z", "anna")
def test_identity(self):
self.assertIsNone(None)
self.assertIsNotNone(0) # 0 не None!
unittest.main(argv=[''], exit=False, verbosity=2)
Вывод:
test_equal (__main__.TestAsserts.test_equal) ... ok test_identity (__main__.TestAsserts.test_identity) ... ok test_membership (__main__.TestAsserts.test_membership) ... ok test_truthy (__main__.TestAsserts.test_truthy) ... ok ---------------------------------------------------------------------- Ran 4 tests in 0.000s OK
assertAlmostEqual — для чисел с плавающей точкой
Числа float нельзя сравнивать на точное равенство: 0.1 + 0.2 не равно ровно 0.3. Для этого есть assertAlmostEqual, который сравнивает с точностью до знаков:
import unittest
class TestFloat(unittest.TestCase):
def test_naive_fails(self):
# 0.1 + 0.2 == 0.30000000000000004 — НЕ ровно 0.3
self.assertNotEqual(0.1 + 0.2, 0.3)
def test_almost(self):
# А так — корректно: близко с точностью по умолчанию (7 знаков)
self.assertAlmostEqual(0.1 + 0.2, 0.3)
def test_places(self):
self.assertAlmostEqual(3.14159, 3.14, places=2)
unittest.main(argv=[''], exit=False, verbosity=2)
Вывод:
test_almost (__main__.TestFloat.test_almost) ... ok test_naive_fails (__main__.TestFloat.test_naive_fails) ... ok test_places (__main__.TestFloat.test_places) ... ok ---------------------------------------------------------------------- Ran 3 tests in 0.000s OK
Правило: любые float сравнивайте через assertAlmostEqual, иначе тест будет случайно падать из-за погрешности.
Сравнение коллекций
Для списков и словарей assertEqual работает «из коробки» и красиво показывает разницу. Есть и специальные методы: assertListEqual, assertDictEqual, assertCountEqual (равенство без учёта порядка элементов).
import unittest
class TestCollections(unittest.TestCase):
def test_list(self):
self.assertEqual([1, 2, 3], [1, 2, 3])
def test_order_independent(self):
# Одинаковые элементы, разный порядок
self.assertCountEqual([3, 1, 2], [1, 2, 3])
def test_dict(self):
self.assertEqual({"a": 1, "b": 2}, {"b": 2, "a": 1})
unittest.main(argv=[''], exit=False, verbosity=2)
Вывод:
test_dict (__main__.TestCollections.test_dict) ... ok test_list (__main__.TestCollections.test_list) ... ok test_order_independent (__main__.TestCollections.test_order_independent) ... ok ---------------------------------------------------------------------- Ran 3 tests in 0.000s OK
assertTrue против assertEqual: тонкий момент
Соблазнительно всё проверять через assertTrue: self.assertTrue(a == b). Но так делать не стоит. Если такая проверка упадёт, вы увидите лишь сухое «False is not true» — без значений a и b. А assertEqual(a, b) при провале покажет оба значения и их разницу. Правило: используйте самый конкретный подходящий метод. Для равенства — assertEqual, для вхождения — assertIn, для None — assertIsNone. assertTrue/assertFalse оставляйте для настоящих булевых проверок, где значение и так очевидно.
assertIs против assertEqual
Ещё пара, которую путают. assertEqual проверяет равенство значений (через ==), а assertIs — тождество объектов (через is, тот же объект в памяти). В большинстве тестов вам нужен assertEqual. assertIs уместен в особых случаях: проверить, что функция вернула именно None, тот самый синглтон или конкретный закэшированный объект. Для None есть отдельный удобный assertIsNone, который читается яснее, чем assertIs(x, None).
Итог
- Методы
TestCaseдают понятную диагностику — предпочитайте их голомуassert. - Базовый набор:
assertEqual,assertTrue/False,assertIn,assertIsNone. - Для float — только
assertAlmostEqual, неassertEqual. assertCountEqualсравнивает коллекции без учёта порядка.