Snowflake Knowledge - INSIGHT LAB

【Snowflakw×dbt】dbtで実行可能な2つのunit-testを比較してみた

作成者: TAKA|2024年4月10日

みなさん初めまして!INSIGHT LAB株式会社のTAKAと申します。
私は業務で主にデータ分析基盤の構築を行っており、Snowflakeとdbt coreを使用しています。近頃、dbtがv1.8へアップグレードされ、Unit testsが使えるようになるとのことで、折角なら今現在使えるdbt-unit-testingとどう違うのか、このブログで検証してみようと思います。

Unit testsとは

そもそも、Unit testsが何かというと、作成したモデルの機能を検証するためのテストとなります。今までのdbt testは、ソースのデータ品質やモデルのアウトプットデータを検証するデータのテストがメインで、機能を検証するテストはあまり行えませんでした。そのため、今まではdbt-unit-testingというパッケージを使用することで、機能検証するためのテストを実施できましたが、v1.8からはなんとパッケージを使用せずとも、dbtの標準機能としてモデルの機能を検証するUnit testsが使用できるようになります。

検証環境

今回は以下環境で検証します。

Unit testsの検証

それでは、Unit testsを検証していきます。

1.dbt-unit-testingを使用したUnit tests

まずは、dbt-coreのインストールから行います。DWHにSnowflakeを使用するため、dbt-snowflakeをインストールします。

pip install dbt-snowflake

次に、Unit testsを実行するために、パッケージdbt-unit-testingをインストールします。パッケージをインストールするには、packages.ymlに以下コードを記載して、dbt depsコマンドでインストールします。

ちなみに、今回Unit testsでテストするモデルは以下になります。このモデルでは3つのインプットデータを使用して、注文日の最小値や最大値を取得したり、注文ID毎の注文額を集計した後に、1つのテーブルに纏めています。

それでは、Unit testsに使用するテストを用意します。 今回はjaffle_shopのdbtプロジェクトフォルダ内のtestsフォルダに、以下テスト用の.sqlファイルを用意します。

上記の.sqlファイルは、Unit testsに使用するインプットデータとその期待値を表しています。インプットデータの内容は、顧客IDが'1'の顧客の2024年1月1日~5日までの注文履歴を表しており、このインプットデータを元にして、customers.sqlモデルを実行した結果、期待値として設定したデータ通りの結果となることを検証するテストとなっております。今回の期待値としては、顧客IDが'1'の初回注文日や最新注文日、注文額の合計が想定通りになっていることとなります。
それでは、1つずつ見ていきます。

1行目は、必ず指定する必要があります。

3行目では、テストしたいモデルとモデルの説明を記載します。

5行目以降で、テストに使用するインプットのモデルとテストデータを指定します。

インプットのモデル指定には、mock_ref以外にもソースを指定するmock_sourceもあり、モデル毎に指定する必要があります。テストデータは、下記のようにmock_ref(mock_source)内のselectで指定が可能で、複数行設定したい場合はunionすることが可能です。

23行目でアウトプットとなるテストの期待値をexpectとして指定できます。

ここまで準備ができれば、実際にテストを行っていきます。テストの実施には、普段通りにdbt test を使用できます。1行目でtagを指定しているため、以下のようにタグを指定してテストも行えます。

dbt test --select tag:unit-test

テストした結果が以下になります。

テストが正常終了しており、期待値通りの処理が行えていることを確認できました。ここで、stg_paymentsのテストデータを変更して、テストが失敗するパターンを実行してみます。今回はamountの値を+100します。

再度実行すると、キャプチャのようにエラーとなりました。



期待値に対して、実際にモデルを実行した結果が表示されており、エラーの原因がどこか分かりやすくなってますね。
ここまでが、dbt-unit-testingを使用したUnit testsとなります。

2.v1.8から使用できるUnit tests

続いて、v1.8から使用できるようになったUnit testsを検証していきます。
こちらでも、まずはdbt-coreのインストールから始めます。

pip install dbt-core==1.8.0b1

pip install dbt-snowflake==1.8.0b1

 

v1.8はまだベータ版のため、1.8.0の後ろにベータ版のバージョン(今回であれば、b1)を付けてインストールします。また、v1.8からの変更点として、v1.8以前まではdbt-snowflakeをインストールするだけでdbtを使えましたが、v1.8からはdbt-coreもインストールする必要があるため、注意が必要となります。

次に、v1.8で使用するテストを用意します。
v1.8以前では、パッケージをインストールしてましたが、v1.8ではインストールせずともUnit testsを使えるため、packages.ymlの記載は省略してUnit testsを記載していきます。packages.ymlの記載とdbt depsを実行する手間が省けるので、この点はv1.8の方が楽ですね。

そして、dbt-unit-testingでは.sqlファイルにコードを記載していましたが、v1.8では.ymlにテストを記載していきます。

テストの内容としてはdbt-unit-testingと同じになります。v1.8ではmacroを使用しない分、コードが少し短く、かつ、シンプルに感じました。

記載についてですが、1行目でunit_testを指定し、namedescriptionを記載します。

4行目のmodelでテストしたい対象のモデルを指定し、given以降でテストする条件を指定します。inputではインプットとなるモデル、rowsでインプットデータを設定します。

expectで期待値を指定します。

.ymlファイルにUnit testsを記載したので、最後にdbt testを行っていきます。nameを指定しているので、test実施時にnameを指定してテストすることもできます。

dbt test --select sample_test

テストした結果が以下になります。

テストが正常終了しており、期待値通りの処理が行えていることを確認できました。ここでも、stg_paymentsのテストデータを変更して、テストが失敗するパターンを実行してみます。今回はamountの値を-100します。

再度実行すると、キャプチャのようにエラーとなりました。

dbt_unit_testingよりも、結果がシンプルですね。
以上がv1.8を使用したUnit testsとなります。

まとめ

dbt_unit_testingとv1.8でできるようになったUnit testsを比較してみましたが、パッケージをインストールする手間が減ったり、テストコードをシンプルに書けたりとv1.8の方が使いやすそうと感じました。ただ、dbt_unit_testingとv1.8のUnit testsも実務では使っていないので、色々使っていく中で、dbt_unit_testingの方が使いやすい場面もあるのかなとも感じました。どちらにしても、モデルの機能を検証するテストはとても有用なテストだと感じたので、これから実務にも取り入れていきたいと思います。皆さんも気になれば、ぜひ使ってみてください!