- Why: - formalize complete end-to-end verification for the demo DWH stack - provide fast regression checks and full validation before demo/release - What: - add new TEST_PLAN.md with two execution contours: Smoke and Full - include checks for infra bootstrap, Airflow DAG flow, STG/ODS/DDS/DM data quality, monitoring and alert provisioning - add dedicated scenario proving dirty records are captured in ods.*_errors without breaking ETL - Check: - aligned steps with current DAG parameters/tasks and SQL transformation flow - validated expected alert names against Grafana provisioning files
11 KiB
11 KiB
План тестирования стенда (Smoke + Full)
Документ описывает два контура проверки системы:
- быстрый
smokeдля регрессий после изменений; - полный
fullдля финальной валидации end-to-end.
Цель
Проверить, что стек Kafka + ClickHouse + Airflow + Superset + Prometheus/Grafana:
- стабильно поднимается;
- загружает данные по пути
kafka_load -> STG -> etl_pipeline -> ODS/DDS/DM; - корректно обрабатывает «грязные» записи (ошибки фиксируются в ODS, пайплайн не падает);
- отдает метрики и дашборды мониторинга.
Общие принципы
- По умолчанию используем малый срез (
limit=50) для быстрых и повторяемых проверок. - Полный прогон (
limit=0) выполняем отдельно как long-run сценарий. - Основной путь запуска — через Airflow DAG.
- Критерий успеха: не только
SuccessDAG, но и проверки данных/ошибок/мониторинга.
Контур A: Smoke (быстрый)
Ожидаемая длительность: ~10-20 минут.
A.1 Подготовка окружения
# Полная очистка стенда
make clean
# Запуск инфраструктуры
make up
# Проверка контейнеров
docker compose ps
Ожидаем:
airflow-initвExited (0);- остальные сервисы в
Up(включаяsuperset,prometheus,grafana,kafka-exporter,statsd-exporter).
A.2 DDL и минимальная загрузка данных
# Инициализация схемы
docker compose exec -T airflow-webserver airflow dags trigger ddl_init
# Быстрый ingest: по 50 строк на поток
docker compose exec -T airflow-webserver airflow dags trigger kafka_load \
--conf '{"limit": 50, "reset_topics": true}'
Проверки:
# STG не пустой
docker compose exec -T clickhouse clickhouse-client --user=default --password=123456 \
--query "
SELECT 'browser_raw' AS table, count() AS cnt FROM stg.browser_raw
UNION ALL
SELECT 'location_raw', count() FROM stg.location_raw
UNION ALL
SELECT 'device_raw', count() FROM stg.device_raw
UNION ALL
SELECT 'geo_raw', count() FROM stg.geo_raw
"
Ожидаем: во всех 4 таблицах cnt > 0.
A.3 ETL и проверки слоев
docker compose exec -T airflow-webserver airflow dags trigger etl_pipeline \
--conf '{"full_refresh": true}'
Проверки:
# ODS / DDS / DM
docker compose exec -T clickhouse clickhouse-client --user=default --password=123456 \
--query "
SELECT 'ods.browser_event' AS table, count() AS cnt FROM ods.browser_event
UNION ALL
SELECT 'dds.event', count() FROM dds.event
UNION ALL
SELECT 'dds.click', count() FROM dds.click
UNION ALL
SELECT 'dm.dq_summary', count() FROM dm.dq_summary
"
# Базовая целостность DDS (ожидаем 0 orphan-событий)
docker compose exec -T clickhouse clickhouse-client --user=default --password=123456 \
--query "
SELECT countIf(click_id IS NOT NULL AND click_id NOT IN (SELECT click_id FROM dds.click)) AS orphan_events
FROM dds.event
"
Ожидаем:
ods.browser_event,dds.event,dm.dq_summary> 0;orphan_events = 0.
A.4 Smoke мониторинга
# Prometheus targets
curl -s http://localhost:9090/api/v1/targets | grep -o '"health":"[^"]*"'
# Grafana health
curl -s -u admin:admin http://localhost:3000/api/health
# Дашборды по UID
curl -s -u admin:admin "http://localhost:3000/api/dashboards/uid/clickhouse-overview" | grep -o '"title":"[^"]*"'
curl -s -u admin:admin "http://localhost:3000/api/dashboards/uid/kafka-overview" | grep -o '"title":"[^"]*"'
curl -s -u admin:admin "http://localhost:3000/api/dashboards/uid/airflow-overview" | grep -o '"title":"[^"]*"'
Критерий успеха smoke:
- сервисы подняты;
- 3 DAG (
ddl_init,kafka_load,etl_pipeline) успешны; - данные проходят до DM;
- мониторинг и дашборды доступны.
Контур B: Full (полный)
Ожидаемая длительность: ~30-60 минут.
B.1 Полная загрузка и полный ETL
# Чистый старт
make clean && make up
# DDL
docker compose exec -T airflow-webserver airflow dags trigger ddl_init
# Полный ingest (все строки)
docker compose exec -T airflow-webserver airflow dags trigger kafka_load \
--conf '{"limit": 0, "reset_topics": true}'
# Полный ETL
docker compose exec -T airflow-webserver airflow dags trigger etl_pipeline \
--conf '{"full_refresh": true}'
B.2 Проверка объемов и DQ
# Фактические размеры входа
wc -l data/*.jsonl
# Сводка по слоям
docker compose exec -T clickhouse clickhouse-client --user=default --password=123456 --query "
SELECT 'STG' as layer, sum(rows) as total_rows FROM (
SELECT count() as rows FROM stg.browser_raw UNION ALL
SELECT count() FROM stg.location_raw UNION ALL
SELECT count() FROM stg.device_raw UNION ALL
SELECT count() FROM stg.geo_raw
) UNION ALL
SELECT 'ODS', sum(rows) FROM (
SELECT count() FROM ods.browser_event UNION ALL
SELECT count() FROM ods.location_event UNION ALL
SELECT count() FROM ods.device_by_click UNION ALL
SELECT count() FROM ods.geo_by_click
) UNION ALL
SELECT 'DDS', sum(rows) FROM (
SELECT count() FROM dds.event UNION ALL
SELECT count() FROM dds.click
)"
# DQ summary
docker compose exec -T clickhouse clickhouse-client --user=default --password=123456 \
--query "SELECT * FROM dm.dq_summary ORDER BY layer, table_name, check_name"
Критерии успеха full:
- STG заполнен по всем 4 потокам;
- ODS/DDS/DM заполнены;
dm.dq_summaryне пуста и содержит метрики всех слоев.
B.3 Тест восстановления stop/start
# Остановить без удаления данных
docker compose stop
# Проверить volumes
docker volume ls | grep -E 'clickhouse-data|kafka-data|pgmeta|grafana_lib|superset_data|superset_config'
# Поднять обратно
docker compose start
# Проверить, что данные сохранились
docker compose exec -T clickhouse clickhouse-client --user=default --password=123456 \
--query "SELECT count() FROM dds.event"
Сценарий C: «Грязные» данные не валят пайплайн
Цель: доказать, что невалидные записи фиксируются в ods.*_errors, а ETL завершается успешно.
Предусловие: выполнен Контур A или Контур B (в STG уже есть валидные данные).
C.1 Инъекция невалидных записей в STG
# browser: невалидные UUID и timestamp
docker compose exec -T clickhouse clickhouse-client --user=default --password=123456 \
--query "INSERT INTO stg.browser_raw (raw) VALUES ('{\"event_id\":\"bad-uuid\",\"event_timestamp\":\"bad-ts\",\"click_id\":\"bad-click\",\"event_type\":\"pageview\"}')"
# location: невалидный event_id
docker compose exec -T clickhouse clickhouse-client --user=default --password=123456 \
--query "INSERT INTO stg.location_raw (raw) VALUES ('{\"event_id\":\"bad-uuid\",\"page_url\":\"https://example.com\"}')"
# device: невалидные click_id и user_domain_id
docker compose exec -T clickhouse clickhouse-client --user=default --password=123456 \
--query "INSERT INTO stg.device_raw (raw) VALUES ('{\"click_id\":\"bad-uuid\",\"user_domain_id\":\"bad-uuid\",\"device_type\":\"Mobile\"}')"
# geo: невалидные click_id и координаты
docker compose exec -T clickhouse clickhouse-client --user=default --password=123456 \
--query "INSERT INTO stg.geo_raw (raw) VALUES ('{\"click_id\":\"bad-uuid\",\"geo_latitude\":\"abc\",\"geo_longitude\":\"def\"}')"
C.2 Повторный ETL
docker compose exec -T airflow-webserver airflow dags trigger etl_pipeline \
--conf '{"full_refresh": true}'
Ожидаем: DAG etl_pipeline завершен в Success.
C.3 Ассерты по ошибкам
# Ошибки должны попасть в *_errors таблицы
docker compose exec -T clickhouse clickhouse-client --user=default --password=123456 \
--query "
SELECT 'browser_event_errors' AS table, count() AS cnt FROM ods.browser_event_errors
UNION ALL
SELECT 'location_event_errors', count() FROM ods.location_event_errors
UNION ALL
SELECT 'device_by_click_errors', count() FROM ods.device_by_click_errors
UNION ALL
SELECT 'geo_by_click_errors', count() FROM ods.geo_by_click_errors
"
# При этом пайплайн продолжает давать бизнес-слой
docker compose exec -T clickhouse clickhouse-client --user=default --password=123456 \
--query "SELECT count() FROM dds.event"
Критерии успеха сценария C:
etl_pipelineне падает;- хотя бы одна
*_errorsтаблица увеличилась; dds.eventостается непустой (валидные данные продолжают обрабатываться).
Проверка алертов (фактический набор)
Проверяем, что в Grafana загружены именно текущие provisioned-правила:
curl -s -u admin:admin http://localhost:3000/api/v1/provisioning/alert-rules | grep -o '"title":"[^"]*"'
Ожидаемые правила:
- ClickHouse:
ClickHouse Failed Queries RateClickHouse Memory Resident HighClickHouse Parts Active High
- Airflow:
Airflow Scheduler DownAirflow Queue BacklogHigh Task Failure RateHigh DAG Parse Time
- Kafka:
Kafka Broker DownKafka Consumer Lag HighKafka No Messages Produced
Финальный чек-лист приемки
Smokeпроходит стабильно после изменений в коде.Fullпроходит перед демонстрацией/релизом.- Сценарий
Грязные данныеподтверждает, что ошибки локализуются в ODS и не ломают ETL. - Метрики и дашборды доступны, алерты совпадают с текущей конфигурацией provisioning.