みなさん初めまして!INSIGHT LAB株式会社のTAKAと申します。
私は業務で主にデータ分析基盤の構築を行っており、Snowflakeとdbt coreを使用しています。近頃、dbtがv1.8へアップグレードされ、Unit testsが使えるようになるとのことで、折角なら今現在使えるdbt-unit-testingとどう違うのか、このブログで検証してみようと思います。
そもそも、Unit testsが何かというと、作成したモデルの機能を検証するためのテストとなります。今までのdbt testは、ソースのデータ品質やモデルのアウトプットデータを検証するデータのテストがメインで、機能を検証するテストはあまり行えませんでした。そのため、今まではdbt-unit-testingというパッケージを使用することで、機能検証するためのテストを実施できましたが、v1.8からはなんとパッケージを使用せずとも、dbtの標準機能としてモデルの機能を検証するUnit testsが使用できるようになります。
今回は以下環境で検証します。
それでは、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となります。
続いて、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を指定し、name
やdescription
を記載します。
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の方が使いやすい場面もあるのかなとも感じました。どちらにしても、モデルの機能を検証するテストはとても有用なテストだと感じたので、これから実務にも取り入れていきたいと思います。皆さんも気になれば、ぜひ使ってみてください!