dbt搭配dbt_constraints时Singular测试报缺少test_metadata错误
问题根因
v0.3.0版本dbt_constraints包的on-run-end钩子存在逻辑缺陷:脚本遍历所有测试节点时,默认所有测试节点都携带test_metadata属性,但实际上只有dbt内置/自定义的通用测试(generic test,如unique、not_null、relationships等)会自动生成该属性,单独编写的Singular单例测试天生不携带这个属性。
测试执行失败时,脚本会在失败结果处理阶段提前返回,不会走到读取test_metadata的步骤,因此不会触发报错;只有测试全部通过时,脚本才会进入后续自动创建约束的流程,尝试读取所有测试节点的test_metadata属性,最终触发编译错误。
解决方案
按落地成本从低到高排序,可选以下三种方案:
- 升级
dbt_constraints包版本
该兼容性bug已经在后续发布的版本中修复,升级后脚本会自动跳过无test_metadata属性的Singular测试节点,不需要修改已编写的测试SQL,升级前注意核对包版本与当前dbt核心版本的适配关系即可。 - 给Singular测试添加禁用dbt_constraints识别的配置
若暂时无法升级包版本,可直接在测试SQL文件头部添加config配置块,标记该测试不需要被dbt_constraints当作约束生成的依据,配置示例如下:
添加配置后,on-run-end钩子会直接跳过该测试节点,不会尝试读取它的{{ config( dbt_constraints_enabled = false ) }} SELECT * FROM {{ ref('TableA') }} WHERE param_1 NOT IN (SELECT TableB_id FROM {{ ref('TableB') }} UNION SELECT TableC_id FROM {{ ref('TableC') }} UNION SELECT TableD_id FROM {{ ref('TableD') }} UNION SELECT TableE_id FROM {{ ref ('TableE') }} ) and param_2 is nulltest_metadata属性,报错即可消除。 - 将Singular测试改写为Generic通用测试
如果该校验逻辑后续需要在多个表/字段上复用,可以把现有逻辑改写成通用测试,这类测试编译时会自动生成test_metadata属性,不会触发该报错,该方案改造成本较高,仅适合需要复用逻辑的场景。
注意:不需要手动为Singular测试补充
test_metadata配置,该字段是dbt编译通用测试节点时自动生成的内部属性,手动配置不会被dbt正常识别,反而可能引发其他编译异常。
内容的提问来源于stack exchange,提问作者nexx
相关产品推荐
相关产品推荐

