🐛 Типичные ошибки при unit-тестировании на pytest

1. Нет префикса test_ в имени функции

pytest не найдёт тест — он просто не запустится, без ошибки.

# Неправильно
def check_sum(calculator):
    assert calculator.sum(4, 5) == 9

# Правильно
def test_sum(calculator):
    assert calculator.sum(4, 5) == 9

2. Сравнение float без round() или pytest.approx()

Числа с плавающей точкой хранятся приблизительно. Прямое сравнение может дать False.

# Может упасть из-за float precision
def test_sum_floats(calculator):
    assert calculator.sum(5.6, 4.3) == 9.9  # AssertionError!

# Правильно (вариант 1 — round)
def test_sum_floats_round(calculator):
    assert round(calculator.sum(5.6, 4.3), 1) == 9.9

# Правильно (вариант 2 — pytest.approx)
def test_sum_floats_approx(calculator):
    assert calculator.sum(5.6, 4.3) == pytest.approx(9.9, rel=1e-1)

3. Мутируемые объекты в фикстуре без reset

Если фикстура возвращает объект со состоянием, которое изменяется в тесте — следующий тест получит «грязный» объект.

# Опасно: если Calculator накапливает состояние
@pytest.fixture
def calculator():
    return Calculator()  # каждый тест получает НОВЫЙ экземпляр — это правильно

# Опасная фикстура (scope="session") с состоянием:
@pytest.fixture(scope="session")
def shared_calculator():
    return Calculator()  # ОДИН объект на все тесты — опасно, если тесты меняют его
Для Calculator без состояния это не проблема. Но помните об этом при работе с объектами типа список, словарь, ORM-сессия.

4. Незарегистрированный пользовательский маркер

pytest выдаст PytestUnknownMarkWarning. В строгом режиме — ошибка.

# Неправильно: маркер не зарегистрирован в pytest.ini
@pytest.mark.positive_test
def test_sum():
    ...

# Правильно: добавить в pytest.ini
# [pytest]
# markers =
#     positive_test: Тесты для позитивных сценариев

5. Неверный формат parametrize — одна строка вместо кортежей

Частая ошибка: передать список значений без кортежей при нескольких параметрах.

# Неправильно: pytest не разберёт аргументы
@pytest.mark.parametrize('a, b, result', [4, 5, 9])  # не кортеж!

# Правильно: каждый набор — кортеж
@pytest.mark.parametrize('a, b, result', [
    (4, 5, 9),
    (-6, -10, -16)
])

6. Не активировано виртуальное окружение — ModuleNotFoundError

pytest не установлен в системном Python или в другом окружении.

# Симптом:
# ModuleNotFoundError: No module named 'pytest'

# Решение:
venv\Scripts\activate      # Windows
pip install pytest

7. Изменение pytest.ini без удаления старых фильтров

В лекции добавляли python_functions = *sum* для выборочного запуска. Если не убрать после упражнения — остальные тесты перестанут запускаться.

# Помните: после упражнения с выборочным запуском
# убрать строку python_functions из pytest.ini
# или запускать с явным указанием: pytest -k "sum"