Создание пользовательских универсальных тестов данных
dbt поставляется с универсальными тестами данных Not Null, Unique, Relationships и Accepted Values. (Ранее они назывались "тестами схемы", и вы все еще можете встретить это название в некоторых местах.) Внутри эти универсальные тесты данных определяются как блоки test
(как макросы).
Существует множество универсальных тестов данных, определенных в open source пакетах, таких как dbt-utils и dbt-expectations — возможно, тест, который вы ищете, уже здесь!
Универсальные тесты со стандартными аргументами
Универсальные тесты определяются в SQL-файлах. Эти файлы могут находиться в двух местах:
tests/generic/
: то есть в специальной подпапке с именемgeneric
в ваших путях тестов (tests/
по умолчанию)macros/
: Почему? Универсальные тесты работают очень похоже на макросы, и исторически это было единственное место, где их можно было определить. Если ваш универсальный тест зависит от сложной логики макросов, вам может быть удобнее определить макросы и универсальный тест в одном файле.
Чтобы определить свои собственные ун иверсальные тесты, просто создайте блок test
с именем <test_name>
. Все универсальные тесты должны принимать один или оба стандартных аргумента:
model
: Ресурс, на котором определен тест, шаблонизированный до его имени отношения. (Обратите внимание, что аргумент всегда называетсяmodel
, даже если ресурс является источником, seed или snapshot.)column_name
: Столбец, на котором определен тест. Не все универсальные тесты работают на уровне столбца, но если они это делают, они должны приниматьcolumn_name
в качестве аргумента.
Вот пример теста схемы is_even
, который использует оба аргумента:
{% test is_even(model, column_name) %}
with validation as (
select
{{ column_name }} as even_field
from {{ model }}
),
validation_errors as (
select
even_field
from validation
-- если это условие истинно, то even_field на самом деле нечетное!
where (even_field % 2) = 1
)
select *
from validation_errors
{% endtest %}
Если этот select
запрос возвращает ноль записей, то каждая запись в переданном аргументе model
четная! Если вместо этого возвращается ненулевое количество записей, то по крайней мере одна запись в model
нечетная, и тест не прошел.
Чтобы использовать этот универсальный тест, укажите его по имени в свойстве tests
модели, источника, snapshot или seed:
version: 2
models:
- name: users
columns:
- name: favorite_number
tests:
- is_even
С одной строкой кода вы только что создали тест! В этом примере users
будет передан в тест is_even
как аргумент model
, а favorite_number
будет передан как аргумент column_name
. Вы можете добавить ту же строку для других столбцов, других моделей — каждая добавит новый тест в ваш проект, используя то же самое определение универсального теста.
Универсальные тесты с дополнительными аргументами
Тест is_even
работает без необходимости указывать какие-либо дополнительные аргументы. Другие тесты, такие как relationships
, требуют больше, чем просто model
и column_name
. Если ваш пользовательский тест требует больше, чем стандартные аргументы, включите эти аргументы в сигнатуру теста, как field
и to
включены ниже:
{% test relationships(model, column_name, field, to) %}
with parent as (
select
{{ field }} as id
from {{ to }}
),
child as (
select
{{ column_name }} as id
from {{ model }}
)
select *
from child
where id is not null
and id not in (select id from parent)
{% endtest %}
При вызове этого теста из .yml
файла, передайте аргументы тесту в виде словаря. Обратите внимание, что стандартные аргументы (model
и column_name
) предоставляются контекстом, поэтому вам не нужно определять их снова.
version: 2
models:
- name: people
columns:
- name: account_id
tests:
- relationships:
to: ref('accounts')
field: id