unittest – це вбудований модуль Python, який надає фреймворк для написання та запуску модульних тестів (unit testing). unittest входить у стандартну бібліотеку Python, тобто не потребує додаткових інсталяцій перед початком роботи.

Основні концепції що підтримуються фреймворком unittest

test fixture: являє собою підготовчі дії, необхідні для виконання одного або декількох тестів, і відповідно дії з очищення після їх виконання. Як приклад, створення тимчасових баз даних, каталогів, запуск серверного процесу, тощо.

test case: окрема одиниця (unit) тестування, що перевіряє певну реакцію на певний набір вхідних даних. unittest надає базовий клас TestCase, який можна використовувати для створення нових тестових кейсів.

test suite: сукупність тестових кейсів, використовується для об’єднання тестів, які повинні виконуватись разом.

test runner: компонент, відповідальний за організацію виконання тестів та надання результатів.

Базовий приклад використання unittest

Припустимо, що у нас є модуль util.py, що містить клас Calculations:

class Calculations:
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def sum(self):
        return self.a + self.b

    def difference(self):
        return self.a - self.b

В модулі test_util.py створимо тести для методів класу Calculations, використовуючи модуль unittest:

import unittest

from util import Calculations


class TestCalculations(unittest.TestCase):

    def test_sum(self):
        calculation = Calculations(1, 5)
        self.assertEqual(calculation.sum(), 10, 'The sum is wrong.')

    def test_difference(self):
        calculation = Calculations(1, 5)
        self.assertEqual(calculation.difference(), -4, 'The difference is wrong.')


if __name__ == '__main__':
    unittest.main()

Щоб використовувати unittest потрібно:

  • створити клас тестів, що успадковує unittest.TestCase
  • всередині тестового класу, визначити тестові методи котрі містять перевірки (ім’я таких методів повинно починатись з test_)
  • використовувати спеціальні методи твердження assert*, для перевірки очікуваних результатів
  • unittest.main() надає інтерфейс командного рядка до тестового скрипту

Щоб виконати ці тести, потрібно просто запустити модуль test_util.py на виконання:

python test_util.py

Результат виглядає наступним чином:

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

OK

Символ крапки у результатах ".", означає що тест пройдено. Якщо до команди запуску додати опцію "-v", можна отримати більш детальний вивід про результат:

python test_util.py -v

Результат:

test_difference (__main__.TestCalculations) ... ok
test_sum (__main__.TestCalculations) ... ok

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

OK

Повний перелік опцій командного рядка доступний за посиланням:

unittest command line options

Методи assert* у unittest

Клас TestCase з модуля unittest, надає перелік методів для перевірки очікуваного результату. Розглянемо деякі з них:

assertEqual(first, second, msg=None) – перевіряє що first та second еквівалентні (подібно до виразу first == second)

assertNotEqual(first, second, msg=None) – перевірка що first та second не еквівалентні (тобто first != second)

assertTrue(expr, msg=None) – перевіряє що expr є істинним (тобто bool(expr) is True)

assertFalse(expr, msg=None) – перевіряє що expr є хибним

assertIs(first, second, msg=None) – перевіряє чи є first та second одним і тим самим об’єктом

assertIsNot(first, second, msg=None) – перевіряє що first та second не є одним і тим самим об’єктом

assertIsNone(expr, msg=None) та assertIsNotNone(expr, msg=None) – перевіряють що expr є None (або навпаки)

assertIn(member, container, msg=None) та assertNotIn(member, container, msg=None) – перевірити чи міститься (або ні) member у container (мається на увазі список, кортеж, тощо)

assertIsInstance(obj, cls, msg=None) та assertNotIsInstance(obj, cls, msg=None) – перевірити чи obj є екземпляром класу cls (або навпаки), подібно до функції isinstance(obj, cls)

assertRaises(exception, callable, *args, **kwds) – перевіряє, чи згенеровано exception під час виклику callable, тест буде пройдено якщо виключення згенеровано

Також зверніть увагу на опціональний атрибут msg у методах assert*, котрий дозволяє додати користувацьке повідомлення, що буде додано до результату якщо тест failed.

Методи setUp() та tearDown()

Клас unittest.TestCase містить методи setUp() та tearDown(), які запускаються перед/після кожного тесту, відповідно. Адаптуємо приклад вище, та винесемо ініціалізацію об’єкта класу Calculations, з тестових методів у метод setUp():

import unittest

from util import Calculations


class TestCalculations(unittest.TestCase):

    def setUp(self):
        self.calculation = Calculations(1, 5)

    def test_sum(self):
        self.assertEqual(self.calculation.sum(), 6, 'The sum is wrong.')

    def test_difference(self):
        self.assertEqual(self.calculation.difference(), -4, 'The difference is wrong.')


if __name__ == '__main__':
    unittest.main()

Підсумок

Наостанок, посилання на сторінку документації:

unittest – Unit testing framework Python