Files
clickstream-ch-kafka-supers…/docs/TEST_PLAN.md
T
ddadmin f411a46aea docs(docs): add comprehensive system test plan
- 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
2026-02-09 09:56:58 +03:00

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.
  • Критерий успеха: не только Success DAG, но и проверки данных/ошибок/мониторинга.

Контур 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 Rate
    • ClickHouse Memory Resident High
    • ClickHouse Parts Active High
  • Airflow:
    • Airflow Scheduler Down
    • Airflow Queue Backlog
    • High Task Failure Rate
    • High DAG Parse Time
  • Kafka:
    • Kafka Broker Down
    • Kafka Consumer Lag High
    • Kafka No Messages Produced

Финальный чек-лист приемки

  • Smoke проходит стабильно после изменений в коде.
  • Full проходит перед демонстрацией/релизом.
  • Сценарий Грязные данные подтверждает, что ошибки локализуются в ODS и не ломают ETL.
  • Метрики и дашборды доступны, алерты совпадают с текущей конфигурацией provisioning.