LESSON 30分

dbtのテストとドキュメント

田中VPoE「モデルが書けるようになったね。でも、SQLが正しく動くだけでは不十分だ。データの品質を自動でチェックする仕組みが必要なんだ。」

あなた「ソフトウェア開発でいうユニットテストのようなものですか?」

田中VPoE「そうだ。dbtにはテスト機能が組み込まれている。さらにドキュメント自動生成もあるから、『このカラムは何を意味するの?』という質問に即答できる環境を作れるんだ。」

dbtテストの種類

dbtには2種類のテストがあります。

種類定義方法ユースケース
Generic TestYAMLファイルで宣言not_null, unique等の汎用チェック
Singular TestSQLファイルで記述複雑なビジネスルールの検証

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_nullNULLがないことを確認必須値の欠損
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 TestYAMLで宣言、unique/not_null/accepted_values/relationships
Singular TestSQLで記述、複雑なビジネスルールの検証
重要度設定error(停止) vs warn(警告のみ)
鮮度チェックソースデータの更新監視
ドキュメントコードから自動生成、DAG可視化

チェックリスト

  • Generic Testの4つの組み込みテストを説明できる
  • Singular Testの書き方を理解している
  • テストの重要度(error/warn)の使い分けができる
  • dbt docs generateでドキュメントを生成できる

次のステップへ

dbtのテストとドキュメント機能を学びました。次は、マクロやパッケージなどdbtの高度な機能について学びましょう。


推定読了時間:30分