Раздел 15. Testing
Containers решают главную проблему интеграционного тестирования: настоящая база данных перестаёт быть дорогим общим ресурсом и становится одноразовым объектом, который создаётся за секунды и удаляется после теста. Это меняет практику — тесты, которые раньше писали «когда-нибудь», становятся выполнимыми.
Раздел разбирает два подхода: Compose-окружение для тестов и Testcontainers, где окружением управляет сам тест. У каждого своя область применения. Отдельно рассматриваются вещи, которые ломают контейнеризованные тесты чаще всего: старт до готовности зависимости, неизолированное состояние между тестами и отсутствие гарантированной очистки.
Цели обучения
После раздела учащийся сможет:
- разделить тесты по уровням и определить, какие из них требуют containers;
- запускать
pytestвнутри образа и использовать exit code как результат сборки; - организовать тестовые зависимости, не раздувая production-образ;
- поднимать одноразовую базу данных для integration tests и гарантированно её удалять;
- реализовать корректную wait strategy вместо
sleep; - обеспечить изоляцию тестов друг от друга при общей базе;
- применять Testcontainers for Python и объяснить, когда он предпочтительнее Compose;
- тестировать сетевое взаимодействие и работу с файловой системой;
- валидировать собранный образ: содержимое, пользователь, точка входа, переменные окружения;
- встроить всё это в pipeline из раздела 16.
Предварительные знания
- Раздел 09. Docker Compose — healthchecks и зависимости;
- Раздел 10. Development workflow — рабочее окружение;
- Раздел 06. Python внутри Container — запуск
pytestв образе; - рабочее знание
pytest: фикстуры, параметризация, маркеры.
Материалы
-
Стратегия тестирования
Уровни тестов и стоимость каждого. Какие тесты требуют реальных зависимостей, а какие только замедляются от них. Пирамида тестов применительно к контейнеризованному сервису. Что тестировать в образе, а что в приложении. Границы ответственности. -
Тесты внутри container
Запускpytestв собранном образе. Отдельная стадияtestв multi-stage build и её остановка сборки при падении тестов. Разделение production и test зависимостей. Монтирование кода для быстрой итерации. Получение отчётов о покрытии из container. -
Integration tests через Compose
Отдельныйcompose.test.yaml. Одноразовая база:tmpfsвместо volume для скорости. Wait strategy через healthcheck иservice_healthyвместоsleep. Изоляция тестов: транзакции, отдельные схемы, пересоздание базы. Гарантированная очистка черезdown -vдаже при падении. Код возврата тестового прогона. -
Testcontainers for Python
Управление окружением из кода теста. Фикстурыpytestс автоматическим запуском и остановкой. Встроенные wait strategies. Переиспользование контейнера между тестами и его риски. Сравнение с Compose-подходом: когда что выбирать. -
Валидация образа
Проверки собранного артефакта: от какого пользователя запускается, какие файлы присутствуют, какая точка входа, какие переменные окружения. Smoke test запущенного container. Проверка healthcheck. Обзор container structure tests. Автоматизация проверок в pipeline. -
Практические задания
Лабораторные задания раздела с проверкой результата.
Рекомендуемый порядок чтения
Последовательный: 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.
Критерии завершения раздела
Раздел пройден, когда учащийся может без подсказок:
- Объяснить, какие тесты требуют реальной базы, а какие нет.
- Запустить integration tests одной командой с автоматическим созданием и удалением окружения.
- Объяснить, почему
sleepперед тестами — источник нестабильности, и заменить его. - Обеспечить изоляцию тестов при общей базе данных.
- Написать проверку, подтверждающую, что образ запускается от non-root.
- Выбрать между Compose и Testcontainers для конкретного проекта и обосновать выбор.
Проверьте себя: Quiz 15.
Что дальше
Тесты есть и запускаются локально. Следующий раздел переносит весь цикл — проверку, сборку, тестирование, публикацию — в автоматический pipeline.
Навигация
← Предыдущий раздел: Registry
Вернуться к главному оглавлению
Следующий раздел: CI/CD →