dbtのテストとドキュメント
田中VPoE「モデルが書けるようになったね。でも、SQLが正しく動くだけでは不十分だ。データの品質を自動でチェックする仕組みが必要なんだ。」
あなた「ソフトウェア開発でいうユニットテストのようなものですか?」
田中VPoE「そうだ。dbtにはテスト機能が組み込まれている。さらにドキュメント自動生成もあるから、『このカラムは何を意味するの?』という質問に即答できる環境を作れるんだ。」
dbtテストの種類
dbtには2種類のテストがあります。
| 種類 | 定義方法 | ユースケース |
|---|---|---|
| Generic Test | YAMLファイルで宣言 | not_null, unique等の汎用チェック |
| Singular Test | SQLファイルで記述 | 複雑なビジネスルールの検証 |
Generic Test
組み込みテスト
dbtに標準で含まれるテストは4つです。
# models/staging/_stg_models.yml
version: 2
models:
- name: stg_orders
description: "注文データのステージングモデル"
columns:
- name: order_id
description: "注文の一意識別子"
tests:
- unique
- not_null
- name: customer_id
description: "顧客ID"
tests:
- not_null
- relationships:
to: ref('stg_customers')
field: customer_id
- name: order_status
description: "注文ステータス"
tests:
- accepted_values:
values: ['pending', 'completed', 'cancelled', 'refunded']
| テスト | 説明 | 検出する問題 |
|---|---|---|
| unique | 重複がないことを確認 | 主キーの重複 |
| not_null | NULLがないことを確認 | 必須値の欠損 |
| accepted_values | 許容値の範囲内か確認 | 不正な値の混入 |
| relationships | 外部キーの整合性を確認 | 参照先の欠損 |
dbt-utilsパッケージのテスト
# packages.yml
packages:
- package: dbt-labs/dbt_utils
version: [">=1.0.0", "<2.0.0"]
# models/marts/_mart_models.yml
models:
- name: mart_daily_revenue
columns:
- name: revenue_date
tests:
- unique
- not_null
- dbt_utils.not_constant
- name: net_revenue
tests:
- dbt_utils.accepted_range:
min_value: 0
inclusive: true
- name: order_count
tests:
- dbt_utils.accepted_range:
min_value: 0
Singular Test
特定のビジネスルールを検証するカスタムSQLテストです。クエリの結果が0行であれば合格です。
-- tests/assert_total_revenue_positive.sql
-- 日次売上が負になっていないことを確認
SELECT
revenue_date,
net_revenue
FROM {{ ref('mart_daily_revenue') }}
WHERE net_revenue < 0
-- tests/assert_order_amount_matches_items.sql
-- 注文金額と明細の合計が一致することを確認
SELECT
o.order_id,
o.order_amount,
i.item_total,
ABS(o.order_amount - i.item_total) AS diff
FROM {{ ref('stg_orders') }} o
LEFT JOIN (
SELECT order_id, SUM(price * quantity) AS item_total
FROM {{ ref('stg_order_items') }}
GROUP BY 1
) i ON o.order_id = i.order_id
WHERE ABS(o.order_amount - i.item_total) > 0.01
テストの実行と設定
実行コマンド
# 全テスト実行
dbt test
# 特定モデルのテスト
dbt test --select stg_orders
# Staging配下のテストのみ
dbt test --select staging.*
# テスト結果をテーブルに保存
dbt test --store-failures
テストの重要度設定
columns:
- name: order_id
tests:
- unique:
severity: error # 失敗でパイプライン停止
- not_null:
severity: error
- name: discount_amount
tests:
- dbt_utils.accepted_range:
min_value: 0
severity: warn # 警告のみ、パイプラインは続行
| 重要度 | 動作 | ユースケース |
|---|---|---|
| error | テスト失敗でパイプライン停止 | 主キー、必須外部キー |
| warn | 警告ログのみ、続行 | ビジネスルールの逸脱 |
ソースの鮮度チェック
データソースが期待通りに更新されているか監視します。
sources:
- name: raw
tables:
- name: orders
loaded_at_field: _etl_loaded_at
freshness:
warn_after: {count: 12, period: hour}
error_after: {count: 24, period: hour}
# 鮮度チェック実行
dbt source freshness
ドキュメント生成
モデルの説明を記述
# models/marts/_mart_models.yml
version: 2
models:
- name: mart_customer_ltv
description: |
顧客のLTV(生涯価値)を計算したマートテーブル。
マーケティングチームが顧客セグメンテーションに使用。
日次更新。
columns:
- name: customer_id
description: "顧客の一意識別子"
- name: ltv_segment
description: |
LTVに基づく顧客セグメント。
- VIP: 注文10回以上かつ売上10万円以上
- High: 注文5回以上かつ売上5万円以上
- Medium: 注文2回以上
- Low: 上記以外
- name: annualized_revenue
description: "年間換算の売上金額"
ドキュメントの生成と閲覧
# ドキュメント生成
dbt docs generate
# ローカルサーバーで閲覧
dbt docs serve --port 8080
生成されるドキュメントには以下が含まれます:
- モデル一覧:全モデルの説明とカラム定義
- DAGビジュアライゼーション:モデル間の依存関係図
- ソース情報:データソースの定義と鮮度状態
- テスト一覧:各モデルに適用されたテスト
まとめ
| 項目 | ポイント |
|---|---|
| Generic Test | YAMLで宣言、unique/not_null/accepted_values/relationships |
| Singular Test | SQLで記述、複雑なビジネスルールの検証 |
| 重要度設定 | error(停止) vs warn(警告のみ) |
| 鮮度チェック | ソースデータの更新監視 |
| ドキュメント | コードから自動生成、DAG可視化 |
チェックリスト
- Generic Testの4つの組み込みテストを説明できる
- Singular Testの書き方を理解している
- テストの重要度(error/warn)の使い分けができる
- dbt docs generateでドキュメントを生成できる
次のステップへ
dbtのテストとドキュメント機能を学びました。次は、マクロやパッケージなどdbtの高度な機能について学びましょう。
推定読了時間:30分