dbt 数据测试是什么
dbt 让数据测试跟着模型一起版本化:在模型 YAML 里声明通用测试(unique、not_null、accepted_values、relationships),也可以写自定义的 singular 测试 SQL。执行 dbt test 或 dbt build 后有失败即返回非零退出码,因此天然适合卡在调度任务与 CI 流水线上——把「数据不对就发布失败」变成默认行为,而不是靠人工抽检。
基本信息
| 通用测试 | unique、not_null、accepted_values、relationships(外键完整性) |
|---|---|
| 声明位置 | 模型 YAML 中 columns 下的 tests 列表 |
| 严重级别 | 可对单个测试设置 warn 或 error,控制是否阻断流水线 |
| 失败留存 | 可配置把失败行写入结果表,便于定位与复盘 |
| 执行方式 | dbt test 只跑测试;dbt build 按依赖顺序跑模型与测试 |
| 集成方式 | 退出码非零即失败,可直接作为发布卡点 |
典型使用场景
- 主键唯一性卡点:模型产出前校验订单明细的唯一键,防止重复行
- 非空校验:金额、时间等关键字段为空时直接阻断发布
- 枚举校验:状态类字段出现字典外取值时报警
- 外键完整性:事实表里的用户或商品号必须在维表中存在
- CI 质量门禁:合并前在测试环境跑一遍模型与测试,防止带病上线
schema.yml 测试声明
schema.yml 测试声明
models:
- name: dwd_trade_order_detail_di
columns:
- name: order_id
tests:
- unique
- not_null
- name: user_id
tests:
- relationships:
to: ref('dim_user')
field: user_id
- name: status_name
tests:
- accepted_values:
values: ['created', 'paid', 'shipped', 'closed']
config:
severity: warn # 告警但不阻断发布自定义测试与执行
自定义测试与执行
# 自定义测试:一条返回问题行的 SQL,返回空集即通过
tests/assert_pay_amount_positive.sql:
select order_id, pay_amount from {{ ref('dwd_trade_order_detail_di') }}
where pay_amount < 0
# 执行:只跑某个模型的测试
dbt test --select dwd_trade_order_detail_di
# 完整构建:按依赖顺序跑模型与测试,任一步失败即中断
dbt build --select +dwd_trade_order_detail_di通用测试用途
| 测试 | 校验什么 | 典型发现 |
|---|---|---|
| unique | 字段取值唯一 | 上游重跑叠加出的重复行 |
| not_null | 字段非空 | 上游新增字段未回填 |
| accepted_values | 取值在枚举集合内 | 源端新增状态码未同步字典 |
| relationships | 外键在目标表中存在 | 孤儿事实行,维度关联后丢行 |
| 自定义 SQL | 任意业务规则 | 金额为负、数量与单价矛盾等 |
relationships 测试等价于外键完整性校验,能提前发现维度找不到的孤儿事实行——这类问题不做测试时往往要等到指标偏低才被察觉。
把严重级别不同的测试混在一起、全部设为 error,会让一个非关键的告警阻断整条发布链路;按影响面分级(阻断 vs 告警)是让质量门禁长期存活的关键。