Встроенные тесты: unique, not_null и другие
Тест данных — это утверждение о том, какими данные должны быть; dbt проверяет его автоматически.
Тест данных — декларативное правило (например «эта колонка уникальна»), которое dbt превращает в SQL-запрос: если он вернёт хоть одну строку-нарушитель, тест провален.
Зачем тестировать данные
Код тестируют, чтобы он не сломался. Данные тестируют по той же причине: первичный ключ задвоился, пришёл NULL там, где не должен, статус оказался неизвестным. Без тестов это всплывает в отчёте перед руководством. С тестами — ловится сразу при dbt test, до того как испорченные данные дойдут до дашборда.
Четыре встроенных теста
Тесты объявляют в YAML рядом с моделью — не в SQL:
# models/marts/_schema.yml
version: 2
models:
- name: fct_orders
columns:
- name: order_id
tests:
- unique # нет дублей
- not_null # нет пропусков
- name: status
tests:
- accepted_values:
values: ['paid', 'shipped', 'delivered', 'cancelled']
- name: customer_id
tests:
- relationships: # ссылочная целостность
to: ref('dim_customers')
field: customer_id
| Тест | Что проверяет |
unique | В колонке нет повторяющихся значений |
not_null | В колонке нет NULL |
accepted_values | Все значения — из разрешённого списка |
relationships | Каждое значение есть в колонке другой модели (внешний ключ) |
Запуск тестов
# Прогнать все тесты
dbt test
# Только тесты одной модели
dbt test --select fct_orders
Если тест падает, dbt покажет, сколько строк нарушили правило, и даст SQL, чтобы их посмотреть.
Как работает под капотом
Каждый тест dbt компилирует в SELECT, который ищет нарушителей. Тест unique превращается примерно в это:
CREATE TABLE fct_orders (order_id INTEGER, status TEXT);
INSERT INTO fct_orders VALUES (1, 'paid'), (2, 'shipped'), (2, 'paid');
-- так выглядит тест unique для order_id:
select order_id, count(*) as n
from fct_orders
group by order_id
having count(*) > 1;
Вывод:
order_id = 2, n = 2 — нарушитель, тест провален
Логика простая: тест проходит, если запрос-нарушитель вернул ноль строк. Это унифицирует все тесты — и встроенные, и ваши собственные.
Частые ошибки
- Не тестировать ключи.
unique+not_nullна первичном ключе — минимум, который ловит самые опасные баги. - Забыть accepted_values на статусах/типах. Новое неожиданное значение тихо ломает логику ниже.
- Игнорировать relationships. Без неё «осиротевшие» внешние ключи всплывают в джойнах как потерянные строки.
Итоги
- Тесты объявляются в YAML и проверяют утверждения о данных:
unique,not_null,accepted_values,relationships. - Под капотом каждый тест — это SQL, ищущий нарушителей; ноль строк = тест пройден.
dbt testловит порчу данных до того, как она дойдёт до дашбордов.