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