🧪

Snowflake&dbt Cloud Quickstart 実践 #10「テストとドキュメント」

に公開

Snowflake社が公開、展開しているdbt Cloudとの連携実践チュートリアル「Accelerating Data Teams with Snowflake and dbt Cloud Hands On Lab」(Snowflakeとdbtクラウドでデータチームを加速するハンズオンラボ)。直近(2025年07月)時点での環境で一通り実践してみました。

https://quickstarts.snowflake.com/guide/accelerating_data_teams_with_snowflake_and_dbt_cloud_hands_on_lab/#0

当エントリでは実施した一連の手順のうち、「10. Tests and Docs」(テストとドキュメント) の内容について実践と解説を行っていきます。

※実施手順の全容については下記をご参照ください。

※これまでの実践内容一覧は以下をご参照ください。

実践#10: テストとドキュメント

モデルや変換を構築した後は、それを文書化しテストすることが非常に重要です。dbtのネイティブ機能には、データテストとドキュメンテーションのフレームワークが含まれており、ドキュメンテーションとテストのニーズをすべて満たすことができます。

テストについて

https://docs.getdbt.com/docs/build/data-tests

dbtでは、2025年07月現在で幾つかのテストに関する手法・機能が提供されています。データテストを定義することは、出力と入力が期待通りであることを確認するための素晴らしい方法です。データテストは何度も繰り返し使用することができ、同じようなアサーションをちょっとした変化で行うことができるため、 一般的なデータテストが多く使われる傾向にあります。テストはその内容と種類によって定義・実行のタイミングとケースが異なります。

  • Singular Test(単一データテスト)
    • 最も単純な形のテスト。失敗した行を返すSQLクエリを書くことができれば、そのクエリをtestディレクトリ内の.sqlファイルに保存可能
    • これはデータテストであり、dbt testコマンドで実行される
  • Generic Test(ジェネリックテスト)
    • 引数を受け付けるパラメータ化されたクエリ。
    • テストクエリは特別なテストブロック(マクロのようなもの)で定義
    • 一旦定義すると、.ymlファイル全体でジェネリックテストの名前を参照することができ、モデル、カラム、ソース、スナップショット、シードに対して定義することができる
    • dbtには4つのジェネリックデータテストが組み込まれている
      • unique:値が一意であることを確認
      • not_null:値がNULLでないことを確認
      • accepted_values:指定した値のセットに含まれていることを確認
      • relationships:外部キーが存在することを確認
  • Unit Test(単体テスト)
    • Unit tests | dbt Developer Hub
    • dbt-core v1.8より導入された仕組み。
    • SQL モデルのロジックの静的テストを実施することが出来る。
  • 関連パッケージを使ったテスト

dbtで実施出来るテストの種類や説明に関しては公式ドキュメントの他にも、下記エントリで分かりやすく説明されています。

https://qiita.com/imaik_/items/f8eee21f9c97fc8045fc
https://belonginc.dev/members/shuhei/posts/dbt-unit-tests
https://datacoves.com/post/dbt-utils-cheatsheet
https://www.datafold.com/blog/top-dbt-utils-and-how-to-use-them-in-your-project
https://www.datafold.com/blog/dbt-expectations
https://ex-ture.com/blog/2025/05/23/how-to-use-dbt_expectations/

ドキュメントについて

https://docs.getdbt.com/docs/build/documentation

dbtは、他のデータチームメンバーや利害関係者が利用できるように、Snowflake情報スキーマの詳細だけでなく、あなたが提供できるカラムとモデルレベルの説明の両方を静的サイトにまとめる機能を有しています。プロジェクトのドキュメントには以下が含まれます:

  • プロジェクトに関する情報
    • モデルコード、プロジェクトの DAG、カラムに追加したテストなど。
  • データウェアハウスに関する情報
    • 列のデータ型、テーブルサイズなど。この情報は、情報スキーマに対してクエリを実行することで生成される。
    • 重要な点として、dbt はモデル、カラム、ソースなどに説明を追加する方法を提供し、ドキュメンテーションをさらに強化

テスト(Tests)と説明(descriptions)を作成

一般的なテストとドキュメントの説明はどちらも YAML ファイルで定義されます。

次のファイルパスで core.yml という新しいファイルを作成し、以下の内容を記載してください。: models/marts/core/core.yml

version: 2

models:
  - name: fct_orders
    description: orders fact table
    columns:
      - name: order_key
        description: primary key of the model
        tests:
          - unique
          - not_null
          - relationships:
              to: ref('stg_tpch_orders')
              field: order_key
              severity: warn
      - name: customer_key
        description: foreign key for customers
      - name: order_date
        description: date of the order
      - name: status_code
        description: status of the order
        tests:
          - accepted_values:
              values: ['P','O','F']
      - name: priority_code
        description: code associated with the order
      - name: clerk_name
        description: id of the clerk
      - name: ship_priority
        description: numeric representation of the shipping priority, zero being the default
      - name: order_count
        description: count of order
      - name: gross_item_sales_amount
        description: '{{ doc("gross_item_sales_amount") }}'
      - name: item_discount_amount
        description: item level discount amount. this is always less than or equal to zero
      - name: item_tax_amount
        description: item level tax total
      - name: net_item_sales_amount
        description: the net total which factors in discount and tax

このファイルにおける要点をそれぞれ以下に記します:

  • 構造
    • ファイルはmodels/marts/core/配下にあり、このディレクトリにあるモデル(この場合はfct_orders)専用のテストと説明が含まれている
      • YAMLファイルとテストし定義するモデルをどのように整理したいかはチーム次第
      • ベストプラクティスとしては、1つのディレクトリに少なくとも1つのテストとドキュメント用のYAMLファイルを持つことを推奨
  • 記載形式
    • トップレベルは記述しているモデルで、モデル名の下に直接モデルレベルの情報を記述
    • また、モデルの説明(description)を記述しており、このモデルのドキュメントサイトを表示すると、これがモデルレベルとして表示される
  • カラムレベルの指定
    • 記述とテストの両方の観点から、ほとんどの作業がここで行われている
    • このモデルのテストは様々なカラムですべての一般的なテストを利用していることがわかる
      • order_keyが一意(unique)、かつnot_nullであることを期待
  • 関連性テスト(`relationship')
    • リレーションシップテスト(relationship')では、このモデルのorder_keystg_tpch_orders`のidとしても存在することを確認
  • accepted valuesテスト
    • status_codeカラムから出力される値が期待に沿うものであることを確認するために、accepted valuesテストを実施
  • 説明(description)
    • 2つの異なる表記に分かれている
      • 1つはプレーンテキストを使い、もう1つはdocブロックへのjinja参照を使っている
    • プレーンテキストの説明はモデルレベルと同じように動作し、YAML ファイルの任意のカラムをドキュメント化できる
    • docブロックは次のステップで説明するmarkdownファイルに記述することを可能にすることで、ドキュメントの機能を拡張

マークダウンファイルのビルド

dbtのドキュメントでは、docブロックの説明に付随するマークダウン・ファイルを作って設定することが出来ます。次のファイルパスでcore.mdという新しいファイルを作成します: models/marts/core/core.md

# the below are descriptions from fct_orders

{% docs gross_item_sales_amount %} same as extended_price {% enddocs %}

このマークダウンファイルはYAMLファイルのdocブロックの説明を持つ1つのカラムに対応する1つのdocブロックを持ちます(マークダウンファイルは複数のdocブロックを持つことができることに注意)。

YAMLのdocブロックの説明の引用符で囲まれた名前はマークダウンファイルの冒頭のdocブロックの名前に接続します。この場合、YAML記述の'{{doc("gross_item_sales_amount") }}'はマークダウンファイルの{% docs gross_item_sales_amount %}にマッチします。この流れでマークダウンファイルのテキストの説明がYAMLファイルの説明として渡され、ドキュメントサイトで対応するモデルを開いたとき、この内容が表示されます。

マークダウンファイルでdocブロックを使って説明文を構築することで、マークダウンで説明文をフォーマットすることができ、カラムやモデルレベルで長い説明文を構築するときに特に役立ちます。また、同じ説明を持つカラムが複数のモデルに存在する場合、そのカラムに対して同じdocブロックを何度でも再利用することができます。docブロックについての詳細は下記ドキュメントをご参照ください。

単一テストのビルド

データベースの説明を見てみると、項目:item_discount_amountはそのカラムの出力が常に0以下であることを指定していることがわかります。であればそれをテストしましょう。この場合、カスタムデータテストを作成する必要があります。

tests/フォルダにfct_orders_negative_discount_amount.sqlというファイルを作成、以下の内容を記載して保存します。

--If no discount is given it should be equal to zero 
--Otherwise it will be negative

select *
  from {{ ref('fct_orders') }}  
 where item_discount_amount > 0

カスタムテストはSQLのselect文として記述され、テストに失敗すると失敗したレコードが出力として返されます。つまり、テストに合格するためには、結果は行を返さないことになり、このことを想定してテストを書く必要があります。item_discount_amountが常に0以下であるという前提で、item_discount_amountが0より大きいかどうかをテストします。select文のwhere句はこのために書かれ、失敗したレコードがあればそれを返します。

このテストをYAMLファイルに記述していない場合、dbtはどうやってこのテストを実行するタイミングを知るのでしょうか?

それは(dbt_project.ymlファイルで定義された)testsディレクトリにあるファイルと、適切なモデルとの依存関係を作成するためにref関数を使うselect文の組み合わせです。こうすることで、dbt testコマンドを使用してそのモデルをテストするときはいつでも、このテストは他のすべてのカラムレベルのテストと一緒に実行されます。

テストの実行

作成したテストの実行をしてみます。以下のコマンドをdbt Cloud IDEで実行。:
dbt test --select fct_orders

モデルの実行と同時にそれぞれのテストが実行されます。

ドキュメントの作成と内容の確認

ドキュメントの作成はコマンド:dbt docs generateで実行可能です。

このコマンドを実行し、完了したらIDEの左上、バージョン管理ペインの上にあるブックアイコンをクリックしてドキュメントを起動してください。

ドキュメントサイトが新しいタブで起動します。読み込み後、一番上の検索バーにfct_ordersと入力し、一番上の結果をクリックすると、そのモデルのドキュメントが表示されます。

読み込みが完了したら、モデルレベルの説明、YAML ファイルに記述したカラムレベルの説明、doc ブロックの説明を見ることができます。

また、テストを持つ2つのカラムに対して実行されるテストへの参照を見ることができます。

更に展開していくと、このモデルと他のモデルとの関係に関する情報も見ることも出来ます。


プロジェクト全体でref関数を使用してモデルを参照することで、dbtが依存関係や系統を構築できるようになるという最終的な結果が上記の内容となります。

リネージグラフは強力な機能で、プロジェクトが大きくなるにつれてさらに強力になり、プロジェクトが成長し続けるにつれて、より多くの情報に基づいたアーキテクチャの議論ができるようになります。

まとめ

というわけで、Snowflake社提供のSnowflake&dbt Cloud実践チュートリアル「Accelerating Data Teams with Snowflake and dbt Cloud Hands On Lab」(Snowflakeとdbtクラウドでデータチームを加速するハンズオンラボ)の実践編、#10「テストとドキュメント」の紹介でした。

次のエントリ「#11」では本番環境へのデプロイ周りについて進めていきます。

参考:

truestarテックブログ
設定によりコメント欄が無効化されています