🙆‍♀️

【dbt Docs】Guides - Writing custom generic tests

2022/03/24に公開

Writing custom generic tests

(カスタム汎用テストを創る)

dbtには、not_null, unique, relationships, accepted_valuesといったテストがかける。models/<filename>.ymlなどで、カラムごとにテストができるやつ。

新たにカスタム汎用テストを書くのもいいけど

  • dbt-utils
  • dbt-expectations
    といった公開済みのテストモジュールもあるのでそちらをまず探すのが良き

Generic tests with standard arguments(標準的な引数での汎用テスト)

汎用テストは以下の二箇所に配置することができる

  • tests/generic/ : test-pathで設定、デフォルトがtests/
  • macros/

カスタム汎用テストを創るには、単に<test_name>というtestブロックを作成するだけ。以下の2つの引数のいずれかを取る必要がある
 - model
 - column_name(option?) :すべてのテストに必要ではないけど

汎用テスト例(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
    -- if this is true, then even_field is actually odd!
    where (even_field % 2) = 1
)
select * from validation_errors
{% endtest %}

このselect文が0件のレコードを返した場合、与えられたmodel引数のすべてのレコードは偶数である!代わりに0以外のレコードが返された場合、modelの中の少なくとも1つのレコードは奇数であり、テストは失敗したことになります。

使い方は

models/<filename>.yml
version: 2

models:
  - name: users
    columns:
      - name: favorite_number
        tests:
          - is_even

たった一行のコードで、テストが作成されました!この例では、users はモデル引数として is_even テストに渡され、favorite_number は column_name 引数として渡されます。他のカラム、他のモデルにも同じ行を追加できます。それぞれが、同じ一般的なテスト定義を使用して、プロジェクトに新しいテストを追加することになります。

Generic tests with additional arguments(追加の引数)

テストに引数を追加することができる

ests/generic/test_relationships.sql
{% 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 %}

使い方

models/<filename>.yml
version: 2

models:
  - name: people
    columns:
      - name: account_id
        tests:
          - relationships:
              to: ref('accounts')
              field: id

Generic tests with default config values(デフォルト設定値による汎用テスト)

汎用テスト定義に config() ブロックを含めることが可能です。そこで設定された値は、特定のインスタンスの .yml プロパティで上書きされない限り、 その汎用テストのすべてのインスタンスに対するデフォルトとなります。

tests/generic/warn_if_null.sql
{% test warn_if_odd(model, column_name) %}
    {{ config(severity = 'warn') }}
    select *
    from {{ model }}
    where ({{ column_name }} % 2) = 1
{% endtest %}

この場合は、テストに失敗した場合重大度(WARN)が通知される

models/<filename>.yml
version: 2

models:
  - name: users
    columns:
      - name: favorite_number
        tests:
          - warn_if_odd         # default 'warn'
      - name: other_number
        tests:
          - warn_if_odd:
              severity: error   # overrides

Customizing dbt's built-in tests

dbtにもともと設定されている汎用テスト(unique,not_nullとか)はプロジェクトで上書きができる

tests/generic/unique.sql
{% test unique(model, column_name) %}

    -- whatever SQL you'd like!

{% endtest %}

Examples

ここでは、コミュニティから寄せられたカスタム汎用(schema)テストの例をいくつか紹介します。

Discussion