Главная/Testing/Обзор

Раздел 15. Testing

Containers решают главную проблему интеграционного тестирования: настоящая база данных перестаёт быть дорогим общим ресурсом и становится одноразовым объектом, который создаётся за секунды и удаляется после теста. Это меняет практику — тесты, которые раньше писали «когда-нибудь», становятся выполнимыми.

Раздел разбирает два подхода: Compose-окружение для тестов и Testcontainers, где окружением управляет сам тест. У каждого своя область применения. Отдельно рассматриваются вещи, которые ломают контейнеризованные тесты чаще всего: старт до готовности зависимости, неизолированное состояние между тестами и отсутствие гарантированной очистки.

Цели обучения

После раздела учащийся сможет:

  • разделить тесты по уровням и определить, какие из них требуют containers;
  • запускать pytest внутри образа и использовать exit code как результат сборки;
  • организовать тестовые зависимости, не раздувая production-образ;
  • поднимать одноразовую базу данных для integration tests и гарантированно её удалять;
  • реализовать корректную wait strategy вместо sleep;
  • обеспечить изоляцию тестов друг от друга при общей базе;
  • применять Testcontainers for Python и объяснить, когда он предпочтительнее Compose;
  • тестировать сетевое взаимодействие и работу с файловой системой;
  • валидировать собранный образ: содержимое, пользователь, точка входа, переменные окружения;
  • встроить всё это в pipeline из раздела 16.

Предварительные знания

Материалы

  1. Стратегия тестирования
    Уровни тестов и стоимость каждого. Какие тесты требуют реальных зависимостей, а какие только замедляются от них. Пирамида тестов применительно к контейнеризованному сервису. Что тестировать в образе, а что в приложении. Границы ответственности.

  2. Тесты внутри container
    Запуск pytest в собранном образе. Отдельная стадия test в multi-stage build и её остановка сборки при падении тестов. Разделение production и test зависимостей. Монтирование кода для быстрой итерации. Получение отчётов о покрытии из container.

  3. Integration tests через Compose
    Отдельный compose.test.yaml. Одноразовая база: tmpfs вместо volume для скорости. Wait strategy через healthcheck и service_healthy вместо sleep. Изоляция тестов: транзакции, отдельные схемы, пересоздание базы. Гарантированная очистка через down -v даже при падении. Код возврата тестового прогона.

  4. Testcontainers for Python
    Управление окружением из кода теста. Фикстуры pytest с автоматическим запуском и остановкой. Встроенные wait strategies. Переиспользование контейнера между тестами и его риски. Сравнение с Compose-подходом: когда что выбирать.

  5. Валидация образа
    Проверки собранного артефакта: от какого пользователя запускается, какие файлы присутствуют, какая точка входа, какие переменные окружения. Smoke test запущенного container. Проверка healthcheck. Обзор container structure tests. Автоматизация проверок в pipeline.

  6. Практические задания
    Лабораторные задания раздела с проверкой результата.

Рекомендуемый порядок чтения

Последовательный: 01 → 02 → 03 → 04 → 05 → exercises.

Уроки 03 и 04 описывают альтернативные подходы. Прочитайте оба, но на практике выберите один — смешивание усложняет проект без выгоды.

Практические задания

ЗаданиеТип
1Добавить стадию test в multi-stage build; сборка должна падать при падении тестовобяз.
2Написать compose.test.yaml с одноразовым PostgreSQL и запустить integration testsобяз.
3Заменить sleep 10 на корректную wait strategy и измерить выигрыш во времениобяз.
4Обеспечить изоляцию тестов: два теста, пишущих в одну таблицу, не должны влиять друг на другаобяз.
5Гарантировать удаление тестового окружения даже при падении тестовобяз.
6Переписать тот же набор тестов на Testcontainers и сравнить подходыдоп.
7Написать проверки собранного образа: UID процесса, отсутствие dev-зависимостей, наличие healthcheckдоп.
8Ускорить прогон integration tests, переведя тестовую базу на tmpfsдоп.
9Тесты проходят локально и падают в CI на подключении к базе. Найти причинудиаг.
10Организовать параллельный запуск тестовых окружений без конфликта портов и имён

Полные формулировки — в exercises.md.

Критерии завершения раздела

Раздел пройден, когда учащийся может без подсказок:

  1. Объяснить, какие тесты требуют реальной базы, а какие нет.
  2. Запустить integration tests одной командой с автоматическим созданием и удалением окружения.
  3. Объяснить, почему sleep перед тестами — источник нестабильности, и заменить его.
  4. Обеспечить изоляцию тестов при общей базе данных.
  5. Написать проверку, подтверждающую, что образ запускается от non-root.
  6. Выбрать между Compose и Testcontainers для конкретного проекта и обосновать выбор.

Проверьте себя: Quiz 15.

Что дальше

Тесты есть и запускаются локально. Следующий раздел переносит весь цикл — проверку, сборку, тестирование, публикацию — в автоматический pipeline.

Навигация

← Предыдущий раздел: Registry
Вернуться к главному оглавлению
Следующий раздел: CI/CD →

Markdown на GitHub ↗