👌

dbt macro tips advent calendar 2022 day 11 - dump_fail_test

2022/12/11に公開

便利なデータ変換ツールである dbt の中のmacroに関するtipsを書いていく dbt macro tips Advent Calendar 2022 11日目です。

実用例 dump_fail_test

コレまで色々と、macroを書くための機能について書いてきましたが、そろそろ1つ実用例を書きたいと思います。
皆さん、testが失敗したとき、どうしてますか?
--store-failures optionを使ったりしているでしょうか?

私は次に示す dump_fail_test macroを使用しています。(※実際に使っているものはもう少し複雑です)

dump_fail_test.sql
{%- macro dump_fail_test(results) %}

  {%- if execute %}
    {%- do log("========== Begin Failure Tests  ==========", info=True) %}
        {% for res in results -%}
            {%- if res.node.unique_id.startswith('test.') and res.node.language == 'sql' and res.status == 'fail' %}
                {%- set sql = res.node.compiled_code %}
                {%- do log("["~res.node.unique_id~"]>\n"~(sql | trim), info=True) %}
                {%- do run_query(sql).print_table(max_rows=20, max_columns=6,max_column_width=None) %}
            {%- endif %}
        {%- endfor %}
    {%- do log("========== End Failure Tests ==========", info=True) %}
  {%- endif %}

{%- endmacro %}

dbt_project.yml
on-run-end:
 - "{{ dump_fail_test(results) }}"
$ dbt build --select my_first_dbt_model
08:48:18  Running with dbt=1.3.1
08:48:19  Found 2 models, 4 tests, 0 snapshots, 0 analyses, 294 macros, 1 operation, 0 seed files, 0 sources, 0 exposures, 0 metrics
08:48:19  
08:48:19  Concurrency: 4 threads (target='dev')
08:48:19  
08:48:19  1 of 3 START sql table model dev.my_first_dbt_model ............................ [RUN]
08:48:19  1 of 3 OK created sql table model dev.my_first_dbt_model ....................... [SELECT 2 in 0.19s]
08:48:19  2 of 3 START test not_null_my_first_dbt_model_id ............................... [RUN]
08:48:19  3 of 3 START test unique_my_first_dbt_model_id ................................. [RUN]
08:48:19  3 of 3 PASS unique_my_first_dbt_model_id ....................................... [PASS in 0.09s]
08:48:19  2 of 3 FAIL 1 not_null_my_first_dbt_model_id ................................... [FAIL 1 in 0.11s]
08:48:19  
08:48:19  Running 1 on-run-end hook
08:48:19  ========== Begin Failure Tests  ==========
08:48:19  [test.macro_tips_advcal.not_null_my_first_dbt_model_id.5fb22c2710]>
select id
from "postgres"."dev"."my_first_dbt_model"
where id is null
| id |
| -- |
|    |
08:48:19  ========== End Failure Tests ==========
08:48:19  1 of 1 START hook: macro_tips_advcal.on-run-end.0 .............................. [RUN]
08:48:19  1 of 1 OK hook: macro_tips_advcal.on-run-end.0 ................................. [OK in 0.00s]
08:48:19  
08:48:19  
08:48:19  Finished running 1 table model, 2 tests, 1 hook in 0 hours 0 minutes and 0.58 seconds (0.58s).
08:48:19  
08:48:19  Completed with 1 error and 0 warnings:
08:48:19  
08:48:19  Failure in test not_null_my_first_dbt_model_id (models/example/schema.yml)
08:48:19    Got 1 result, configured to fail if != 0
08:48:19  
08:48:19    compiled Code at target/compiled/macro_tips_advcal/models/example/schema.yml/not_null_my_first_dbt_model_id.sql
08:48:19  
08:48:19  Done. PASS=2 WARN=0 ERROR=1 SKIP=0 TOTAL=3

このように、on-run-end Contextの results を参照し、SQLのテストかつ失敗しているものについて、描画済みのSQLを取得して、run_queryしてその結果を出力しています。
実行時のログを見れば、どの行が原因で失敗したのかが残っているので非常に便利です。
皆様も使ってみてはどうでしょう。


・・・ じつはこのマクロ実用上では少し困ることが起きるので、追加で改造が必要となります。
12日目はその改造をするために必要なmetaの話をします。

Discussion