Три подхода к тестированию
В лекции последовательно показаны три подхода — от простого к профессиональному. Понять разницу важно, чтобы читать чужой код и знать, когда что применять.
Подход 1: Ручной assert (из лекции — начальный этап)
Лекция начинается с ручного тестирования: создаёт экземпляр Calculator и вызывает assert для каждого случая. Это учебный инструмент для понимания концепции.
# calculator_test.py (ручной подход — из лекции)
from calculator import Calculator
calculator = Calculator()
res = calculator.sum(4, 5)
assert res == 9
res = calculator.sum(-6, -10)
assert res == -16
# ... и так далее для каждого случая
print("Все тесты прошли!")
Проблема: при падении одного assert скрипт немедленно останавливается. Нет никакого отчёта — сколько тестов прошло, сколько упало. Каждый раз нужно запускать вручную.
Подход 2: unittest.TestCase (встроенный модуль Python)
Модуль unittest входит в стандартную библиотеку Python. Используется в старых проектах и корпоративных кодовых базах.
# test_calculator_unittest.py
import unittest
from calculator import Calculator
class TestCalculator(unittest.TestCase):
def setUp(self):
"""setUp вызывается перед каждым тестом — аналог фикстуры pytest."""
self.calculator = Calculator()
def test_sum_positive_numbers(self):
result = self.calculator.sum(4, 5)
self.assertEqual(result, 9)
def test_sum_negative_numbers(self):
result = self.calculator.sum(-6, -10)
self.assertEqual(result, -16)
def test_division_by_zero(self):
with self.assertRaises(ArithmeticError):
self.calculator.div(10, 0)
def test_avg_empty_list(self):
self.assertEqual(self.calculator.avg([]), 0)
if __name__ == "__main__":
unittest.main()
# Запуск unittest:
python -m unittest test_calculator_unittest.py -v
# Вывод:
# test_avg_empty_list (test_calculator_unittest.TestCalculator) ... ok
# test_division_by_zero (test_calculator_unittest.TestCalculator) ... ok
# test_sum_negative_numbers (test_calculator_unittest.TestCalculator) ... ok
# test_sum_positive_numbers (test_calculator_unittest.TestCalculator) ... ok
#
# Ran 4 tests in 0.002s
# OK
Устаревшие методы assertEqual: в старом коде часто встречается
assertEquals (с s) — это алиас, который существует, но устарел. Современный вариант — assertEqual (без s).
Подход 3: pytest (современный — рекомендуется)
Именно этот подход используется в лекции как целевой. pytest работает с обычными функциями Python и обычным assert.
# test_calculator.py (pytest — современный)
import pytest
from calculator import Calculator
@pytest.fixture
def calculator():
return Calculator()
def test_sum_positive_numbers(calculator):
assert calculator.sum(4, 5) == 9
def test_sum_negative_numbers(calculator):
assert calculator.sum(-6, -10) == -16
def test_division_by_zero(calculator):
with pytest.raises(ArithmeticError, match="На ноль делить нельзя"):
calculator.div(10, 0)
def test_avg_empty_list(calculator):
assert calculator.avg([]) == 0
Сравнительная таблица
| Критерий | Ручной assert | unittest.TestCase | pytest |
|---|---|---|---|
| Установка | Не нужна | Не нужна (stdlib) | pip install pytest |
| Синтаксис теста | Скрипт с assert | Класс + self.assert*() | Функция + assert |
| Изоляция тестов | Нет | setUp/tearDown | @pytest.fixture |
| Отчёт при падении | Нет (стоп на первом) | Да | Да (подробный) |
| Маркировки / группировка | Нет | Базовые | Мощные (@mark.*) |
| Применение | Только обучение | Старые проекты, CI | Новые проекты ✓ |
Совет: pytest обратно совместим с unittest — он умеет запускать unittest.TestCase-тесты. В реальных проектах часто встречается смесь обоих подходов.