Основы pytest: первые тесты в Python
pytest это самый распространённый фреймворк для тестирования в Python. У него простой стартовый интерфейс: вы пишете обычные Python-функции с assert, запускаете pytest в терминале — он сам находит тесты и выводит, что прошло и что упало.
Установка
pip install pytest
Первый тест
Производственный код кладём в example.py, тесты в файл рядом с префиксом test_. По этому префиксу pytest и находит тесты автоматически:
1from example import add2 3def test_add_positive():4 assert add(1, 2) == 35 6def test_add_negative():7 assert add(-1, -2) == -38 9def test_add_mixed():10 assert add(5, -2) == 311 Тест это обычная функция, имя начинается с test_, внутри используется стандартный Python-овский assert. Никаких специальных классов, наследований, регистрации.

Запуск
В терминале, в директории с тестами:
pytest
pytest пройдёт по всем test_*.py файлам, запустит все test_* функции внутри и покажет результат:
============================= test session starts ============================== collected 3 items test_example.py ... [100%] ============================== 3 passed in 0.02s ===============================
Точка . рядом с именем файла означает «один тест прошёл». Три точки = три прошли. Для подробного вывода с именами каждого теста — флаг -v:
pytest -v
test_example.py::test_add_positive PASSED [ 33%] test_example.py::test_add_negative PASSED [ 66%] test_example.py::test_add_mixed PASSED [100%]
Когда тест падает
Сломаем тест нарочно (assert add(5, -2) == 10 — заведомо неверно) и запустим pytest:
test_example.py::test_add_mixed FAILED [100%] =================================== FAILURES =================================== ______________________________ test_add_mixed __________________________________ def test_add_mixed(): > assert add(5, -2) == 10 E assert 3 == 10 E + where 3 = add(5, -2) test_example.py:9: AssertionError
pytest показывает:
- где упало (test_example.py:9: AssertionError)
- какое выражение не сработало (assert add(5, -2) == 10)
- что получилось вместо ожидаемого (3 == 10, и что 3 = add(5, -2))
Такой развёрнутый вывод обычно сразу подсказывает причину. Это и есть главный аргумент в пользу обычного assert вместо специальных методов: pytest сам разбирает выражение и показывает интересные части.
Структура теста: Arrange / Act / Assert
По мере роста тестов появляется паттерн, который сильно упрощает их чтение: AAA (Arrange / Act / Assert).
- Arrange: готовим данные, создаём объекты, настраиваем состояние.
- Act: выполняем то самое действие, которое тестируем.
- Assert: проверяем результат.
Python 3.13def test_user_can_change_email(): # Arrange user = User("Anna", "old@example.com") # Act user.change_email("new@example.com") # Assert assert user.email == "new@example.com"
Простой тест assert add(1, 2) == 3 укладывается в одну строку, и AAA там не нужен. Но как только тест больше 3-4 строк, разделение на три блока (комментариями или просто пустыми строками) делает его читаемым с первого взгляда. Это стандарт де-факто в production-коде.
Имена тестов: что_когда_ожидается
В реальных проектах имя теста читается как короткое утверждение о коде. Удобный шаблон: test_<что>_<при каких условиях>_<ожидаемое поведение>:
- test_add_returns_sum_for_positive_numbers, понятнее, чем test_add_1
- test_withdraw_fails_when_balance_is_zero, сразу видно, что и почему
- test_user_email_is_lowercased_after_save, конкретное поведение
Когда такой тест падает в CI, по имени сразу понятно, что именно сломалось, без чтения тела. Это экономит часы дебага в больших проектах.
Проверка понимания
Какое утверждение об основах работы с pytest верно?
В следующей статье возьмём две главные «суперсилы» pytest: фикстуры (для общей настройки тестов) и параметризацию (для запуска одного теста с разными данными).
