dbt test block 简单说明

dbt 的test block实际上是一个jinja2 的扩展,目前主要是test 场景中使用, 此block的实现处理与标准物化的处理是类似的都是jinja2 的扩展

test macro 的创建

按照当前dbt 的版本是分为两中模式,对于tests 路径是可以配置的,包含了tests/generic 以及macros/ ,当然推荐的模式是tests/generic 了

  • 参考定义
    tests/generic/is_even.sql
{% test is_even(model, column_name) %}
 
{{log("call test is_even" ~ model ~ column_name, info=True)}}
 
with validation as (
 
    select
        {{ column_name }} as even_field
 
    from {{ model }}
 
),
 
validation_errors as (
 
    select
        even_field
 
    from validation
    -- if this is true, then even_field is actually odd!
    where (even_field % 2) = 1
 
)
 
select *
from validation_errors
 
{% endtest %}
  • 使用
    方法比较多,包含了基于dbt project 级别的配置,以及模型级别的
    models/app.yaml
version: 2
models:
  - name: mymodel-v2
    columns:
      - name: code
        tests:
          - is_even
  • 运行
dbt compile
dbt test

编译效果

执行效果

扩展定义

  • TestExtension
    新版本的common 模块中
class TestExtension(jinja2.ext.Extension):
    tags = ["test"]
 
    def parse(self, parser):
        node = jinja2.nodes.Macro(lineno=next(parser.stream).lineno)
        test_name = parser.parse_assign_target(name_only=True).name
 
        parser.parse_signature(node)
        node.name = get_test_macro_name(test_name)
        node.body = parser.parse_statements(("name:endtest",), drop_needle=True)
        return node
  • get_test_macro_name 处理
    与其他dbt macro 扩展类似定义了自己的,新版本在 common utils 中
def get_test_macro_name(test_name, with_prefix=True):
    name = f"test_{test_name}"
    return get_dbt_macro_name(name) if with_prefix else name
  • 注册
def get_environment(
    node=None,
    capture_macros: bool = False,
    native: bool = False,
) -> jinja2.Environment:
    args: Dict[str, List[Union[str, Type[jinja2.ext.Extension]]]] = {
        "extensions": ["jinja2.ext.do", "jinja2.ext.loopcontrols"]
    }
 
    if capture_macros:
        args["undefined"] = create_undefined(node)
 
    args["extensions"].append(MaterializationExtension)
    args["extensions"].append(DocumentationExtension)
    args["extensions"].append(TestExtension)

说明

dbt 的test 还是比较强大的,灵活性也比较多,官方是内置了一些test macro,同时也有不少三方工具包,内部上dbt 会将包含test 的解析为resource_type 为test 同时会生成一些对应的sql 模型(只进行执行的不会实践创建)之后还是会调用macro 实现进行check 处理,同时还是
结合配置的severity策略进行提示,实际上内部处理后边会详细介绍下

参考资料

https://docs.getdbt.com/reference/data-test-configs
https://docs.getdbt.com/reference/resource-properties/unit-tests
core/dbt/task/test.py
https://docs.getdbt.com/reference/project-configs/test-paths
https://docs.getdbt.com/reference/resource-configs/severity

posted on 2024-04-23 07:42  荣锋亮  阅读(19)  评论(0编辑  收藏  举报

导航