dbt

dbt-expectationsで実現するGreat Expectations風の豊富な検証

2026-04-19
NicheeLab編集部

dbtはYAMLで宣言的にテストを書き、アダプタ(Snowflake/BigQuery/Redshift/Sparkなど)向けのSQLにコンパイルして実行します(公式: https://docs.getdbt.com/)。dbt-expectationsは、その仕組みの上でGreat Expectationsに近い豊富な検証マクロを提供するコミュニティパッケージです。

この記事では、試験で問われやすい「テストの選択・設定・解釈」の観点と、実務ですぐ使えるYAML例・運用パターンを整理します。パッケージの具体APIは変更され得るため、原則としてdbtの安定仕様(テスト、セレクタ、severity、store_failures、contracts等)に基づいて記述します。

dbt-expectationsの位置づけと試験で問われやすい観点

dbtのテストは「汎用テスト(schema.ymlで宣言)」と「単体データテスト(任意SQL)」に大別されます。dbt-expectationsは前者(汎用テスト)をGreat Expectations風に拡張し、多数の検証マクロをYAMLで簡潔に呼び出せるようにします。試験では、内蔵テスト(not_null, unique, relationships, accepted_values 等)と拡張テストを状況に応じて選べるか、severityの使い分け、テスト結果の解釈(エラー/警告/失敗行の保存)が問われがちです(公式: Testsの基本概念 https://docs.getdbt.com/docs/build/tests)。

ポイントは「テストはSQLにコンパイルされ、対象のモデル/ソースに対して実行される」こと。つまり、記述は宣言的でも、本質は各アダプタ上での集合演算です。テストの負荷・索引利用・日付フィルタは、SQLとして現実的かという観点で判断します。

  • 汎用テスト優先、SQL直書きは最後の手段(可読性と再利用性のため)
  • critical品質はseverity=error、非機能モニタはseverity=warn
  • 大規模テーブルは日付分割や条件指定で負荷を制御
  • CIではセレクタで重要テストのみ短時間で回す(公式: Selection https://docs.getdbt.com/reference/node-selection/syntax)
項目dbt内蔵テストdbt-expectationsGreat Expectations(参照)
定義方法schema.ymlのtestsに簡潔指定schema.ymlで拡張マクロを指定Python/YAMLでexpectationを記述
特徴基本的制約に強い多様な統計/分布/パターン検証極めて表現力が高い
運用負荷最小小〜中(依存パッケージ)中(別ランタイム/オーケストレーション)

dbtテストのコンパイルと実行の流れ(概念)

schema.yml 試験dbt テストマクロアダプタ向けSQL生成DWHで実行結果/失敗行dbtテストのコンパイルと実行の流れ(概念)

packages.yml にdbt-expectationsを追加

packages:
  - package: calogica/dbt-expectations
    version: ">=0.10.0,<1.0.0"  # バージョンは実プロジェクトの互換性に合わせて固定

# 追加後に依存関係を取得
# dbt deps

代表的な検証パターンとYAML例

dbt-expectationsでは、null/重複/範囲/パターン/関係整合/分布に関する検証をYAMLで宣言できます。ビルトインで足りない“複合一意制約”や“数値が非負かつ範囲内”“正規表現パターン”“行レベル条件付き検証”が書きやすくなります。

以下はモデルordersに対する例です。試験観点では、testsセクションの書式、severityの指定、whereやrow_condition等のフィルタ指定の有無を素早く読み解けるかが大切です。

  • 複合キーの一意性: unique_combination_of_columns
  • 値の範囲/非負: expect_column_values_to_be_between, expect_column_values_to_be_increasing
  • カテゴリの網羅性: expect_column_values_to_be_in_set / not_in_set
  • 正規表現パターン: expect_column_values_to_match_regex
  • 欠損・外部キー整合: expect_column_values_to_not_be_null, relationships拡張
検証典型用途SQLに落ちる概念
unique_combination_of_columns自然キーの重複検出GROUP BY + HAVING COUNT(*)>1
expect_column_values_to_be_between閾値チェックBETWEEN / 比較演算
expect_column_values_to_match_regexID/メール等の書式REGEXP系演算子

モデル→テストマクロ→SQL(簡略)

orders (table)expectation macroSELECT ... FROM orders WHERE ...モデル→テストマクロ→SQL(簡略)

schema.yml でのテスト記述例(dbt-expectations)

version: 2
models:
  - name: orders
    description: "受注の正規化済みファクト"
    columns:
      - name: order_id
        tests:
          - not_null
          - unique
      - name: customer_email
        tests:
          - dbt_expectations.expect_column_values_to_match_regex:
              regex: "^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}
NicheeLab を読み込み中…
quot; severity: warn - name: order_amount tests: - dbt_expectations.expect_column_values_to_be_between: min_value: 0 strictly: true severity: error tests: - dbt_expectations.unique_combination_of_columns: combination_of_columns: [order_id, line_number] severity: error - dbt_expectations.expect_table_row_count_to_be_between: min_value: 1 row_condition: "order_date >= dateadd(day, -7, current_date)" # アダプタ方言に合わせる severity: warn

実行と結果解釈:セレクタ・severity・失敗行の保存

dbt testは選択構文で対象を絞れます。タグ付けやモデル名、パス指定などを併用し、ローカルでは軽量に、CIではクリティカルなテストを確実に走らせます(公式: Selection syntax)。severity=warnは失敗してもジョブを失敗扱いにしませんが、結果は記録されます。store_failuresは失敗行を永続テーブルとして残し、原因調査を容易にします(公式: Test configs https://docs.getdbt.com/docs/build/tests#test-configs)。

実務では、P0品質(キー重複、NULL不可、参照整合)はseverity=error、健全性モニタ(分布・傾向・軽微な書式)はseverity=warnに分離し、CIで両方を可視化します。

  • ローカル: dbt test -s orders+
  • CIクリティカル: dbt test -s tag:p0
  • 包括実行: dbt test -m state:modified+ # 差分のみ
  • 失敗行の保存: tests: +store_failures: true(プロジェクト/リソース単位)
設定/実行効果注意点
severity: error失敗でジョブ失敗P0に限定
severity: warn失敗でもジョブ継続可視化は必須
store_failures: true失敗行を調査可能スキーマの掃除/保持期間を決める

選択的にテストを回す運用イメージ

localtag:p0 only (CI)all modified (PR)選択的にテストを回す運用イメージ

dbt_project.yml で失敗行保存・タグ・セレクタを設定

name: your_project
version: 1.0.0
config-version: 2

tests:
  +store_failures: true
  +severity: error  # デフォルト、個別テストで上書き

selectors:
  - name: critical_tests
    definition:
      method: fqn
      value: tag:p0

# 実行例
# dbt test -s @critical_tests

アダプタ差異とパフォーマンス注意点

dbtテストは最終的にアダプタ固有SQLになります。正規表現や日付関数、近似集計の挙動は方言差があります。dbt-expectationsの多くのマクロは方言差を吸収しますが、row_conditionやregexの文字クラスなど、引数に生SQLを渡す部分は自環境の方言に合わせる必要があります。

大規模テーブルでは、パーティションや日付条件を前置し、索引/クラスタリングを活かせるクエリ形状になっているかを確認します。

  • Snowflake: ILIKE/REGEXP, DATEADD/TO_DATEなどの関数名に注意(公式: https://docs.snowflake.com/)
  • BigQuery: REGEXP_CONTAINS/EXTRACT、一部の型キャストに注意(公式: https://docs.getdbt.com/docs/core/connect-data-platform/bigquery)
  • Spark/Databricks: 正規表現・ウィンドウ関数の互換性を確認(公式: https://docs.databricks.com/)
  • row_conditionやregexは方言依存。CIで方言差による失敗を早期検知
プラットフォームよくある差分対処
Snowflake正規表現の方言/大文字小文字REGEXP系の仕様準拠で書く、テストで小さく検証
BigQuery日付の加減算・型DATE/TIMESTAMP関数を明示、SAFE_CASTを検討
Spark/Databricks一部関数の挙動差SQL ANSIモードや関数のドキュメントを参照

負荷軽減のための条件適用イメージ

SELECT ... FROM fact
WHERE event_date >= current_date - 7  -- まず期間を絞る
  AND partition_col = '2026-04-01'    -- パーティションをヒット

条件付き検証(row_condition / where の使い分け例)

models:
  - name: fact_sessions
    tests:
      - dbt_expectations.expect_column_values_to_be_between:
          column: session_duration_sec
          min_value: 0
          row_condition: "event_date >= dateadd(day, -1, current_date)"  # 方言に合わせる

  - name: dim_user
    columns:
      - name: email
        tests:
          - dbt_expectations.expect_column_values_to_match_regex:
              regex: "^[^@\s]+@[^@\s]+\.[^@\s]+
NicheeLab を読み込み中…
quot; where: "is_test_user = false" # 一部マクロではwhereではなくrow_conditionを使用

モデル契約(Contracts)とドキュメント化の相乗効果

dbtのモデル契約(contracts)は、カラム名・型・null許可などのスキーマをビルド時に強制できます(公式: Contracts https://docs.getdbt.com/docs/build/schemas#enforcing-model-contracts)。テストはデータ内容の健全性、contractsはスキーマ形状の保証と役割が異なります。両者を併用すると、API的な互換性とデータ品質の両輪を担保できます。

試験では「どの要件をcontractsで、どれをテストで担保するか」を問われがちです。型・必須列・命名はcontracts、分布/統計/関係はテスト、と整理すると回答しやすくなります。

  • contractsはビルド時エラー、テストはビルド後の検証
  • API互換性はcontracts、ビジネス品質はtests
  • ドキュメントはdescription/propertiesで自動生成(docs generate)
手段強み向いている要件
contractsスキーマを即時強制型/必須列/命名・公開インターフェース
内蔵テスト基礎品質の網羅NULL/一意/参照整合/受容値
dbt-expectations高度な内容検証分布/範囲/書式/複合性

contractsとtestsの適用タイミング

dbt run (build)
  |-- contracts enforce (スキーマ)
  `-- models built
      `-- dbt test (内容検証)

モデルにcontractsを設定しつつテストも併用

models:
  - name: fct_orders
    config:
      contract: {enforced: true}
    columns:
      - name: order_id
        data_type: integer
        constraints:
          nullable: false
        tests:
          - unique
      - name: order_amount
        data_type: numeric
        tests:
          - dbt_expectations.expect_column_values_to_be_between:
              min_value: 0
              strictly: true

チーム運用:ルール化・CI・タグ設計

品質ルールをタグとセレクタに落とし、PRで差分のみ・mainで全量・スケジュールで拡張テストという3段階を回すと、速度と品質が両立します。失敗行保存のスキーマ、保持期間、通知方法(CIアーティファクト/BIダッシュボード)も合意しておきます。

dbt-expectationsの採否は段階的に。まずは内蔵テストでP0を固め、次に重要ドメインへ拡張テストを追加、最後に広範囲へ水平展開すると移行コストが抑えられます。

  • タグ: p0(必須)/ p1(推奨)/ monitor(健全性)
  • selectors.ymlでCIプリセットを定義
  • mainは全量、PRはstate:modified+で差分短縮
  • 失敗行テーブルは日次でクリーンアップ(期限管理)
環境推奨コマンド/セレクタ目的
開発(ローカル)dbt test -s model_name+対象限定で素早い検証
PR(CI)dbt test -s state:modified+ tag:p0差分とP0のみで高速に失敗検知
本番スケジュールdbt test -s tag:p0,tag:monitor品質担保と健全性モニタ

段階的なテスト実行ストラテジ

PRmodified+ & p0mainall p0dailyp0+monitor段階的なテスト実行ストラテジ

selectors.yml の例(CI向け)

selectors:
  - name: pr_critical
    definition:
      union:
        - method: state
          value: modified+
        - method: tag
          value: p0
  - name: daily_quality
    definition:
      union:
        - method: tag
          value: p0
        - method: tag
          value: monitor

# 実行例
# dbt test -s @pr_critical
# dbt test -s @daily_quality

問題で確認

Analytics Engineer

問題 1

売上ファクトモデルで、(order_id, line_number)の複合一意性をエラーとして厳格に担保しつつ、amountが0以上であるかは警告として監視したい。SQLを自作せずYAMLで簡潔に記述する最適なアプローチはどれか?

  1. dbt-expectationsのunique_combination_of_columnsをseverity=error、expect_column_values_to_be_between(min=0)をseverity=warnで定義する
  2. 単体データテストで2本のSQLを自作し、失敗時はどちらもエラー終了にする
  3. モデルcontractsのみを設定し、内容検証は行わない
  4. Great Expectationsを別ジョブで実行し、dbt側ではテストしない

正解: A

要件はYAMLで宣言的に表現でき、複合一意はdbt-expectationsの代表的マクロで対応可能。内容の重要度差はseverityで表現できる。SQL自作や別ツール導入は今回の要件には過剰。

よくある質問

dbt-expectationsは公式機能ですか?試験で必須ですか?

コミュニティパッケージです。試験は公式のテスト概念(汎用/単体、severity、セレクタ等)理解が中心で、特定パッケージAPI暗記は前提ではありません。ただし、拡張テストを使う判断軸は有用です(公式: https://docs.getdbt.com/、認定: https://www.getdbt.com/certifications/analytics-engineer-certification-exam)。

大規模テーブルでテストが重いときの実践策は?

期間や対象を絞るrow_condition/whereの活用、クラスタリング/パーティションキーを先頭でフィルタ、頻度を下げたmonitorタグに分離、失敗行保存で原因を局所化、差分セレクタ(state:modified+)で開発・CIの負荷を抑える、などが現実的です。

contractsとテストはどちらを優先すべきですか?

役割が異なります。スキーマ互換性(型・必須列)はcontractsで即時強制、データ内容の品質(一意・分布・範囲・書式・外部キー整合)はテストで継続検証、という二段構えが推奨です。

この記事で学んだ内容を問題で確認しましょう

16,000問以上の問題で実力チェック

無料で問題を解いてみる
この記事の著者

NicheeLab編集部

データエンジニアリング・クラウド資格の専門家。Databricks・Snowflake等の認定資格を保有し、実務経験に基づいた問題作成・解説を行っています。NicheeLab運営。


関連記事
dbt

dbt Model の基礎: SQL で定義する変換の最小単位

Analytics Engineer 向けに、dbt Model の定義、マテリアライゼーション、依存関係、インクリメン...

dbt

dbt Analytics Engineer 試験ガイド: 出題範囲・配点・申込の実務視点

dbt Analytics Engineer 認定の出題範囲、配点の考え方、申込から受験までの流れを、公式ドキュメントの...

dbt

dbt Cloud と dbt Core の違いと選び方:Analytics Engineer 試験に効く要点

dbt Cloud と dbt Core の機能差を、実務と資格対策の両面から整理。スケジューリング、IDE、RBAC、...

dbt

dbt プロジェクト構造ガイド: models / seeds / macros の実務レイアウト

Analytics Engineer 向けに、dbt プロジェクトのディレクトリ構造と命名規約、dbt_project....

dbt

dbt_project.yml の読み方:主要設定と命名を最短で掴む

dbt_project.yml の必須キー、命名解決(database.schema.identifier)、設定優先度...

dbtの記事一覧 (100件)
© 2026 NicheeLab All rights reserved.