dbt Tests 資料品質測試

在傳統的資料開發流程中,往往缺乏自動化測試的環節。這導致我們經常是在 Dashboard 數字不對、或是 CEO 發現報表怪怪的時,才回過頭來 debug。

dbt 將軟體開發的 TDD (測試驅動開發) 概念引入資料領域。透過編寫測試,我們可以:

  1. 提早發現問題:在 pipeline 執行階段就攔截錯誤資料。
  2. 建立信任:確保提供給使用者的資料是通過驗證的。
  3. 防止退化 (Regression):確保新的程式碼修改不會破壞既有的邏輯。

在 dbt 中,測試的核心邏輯很簡單:只要測試的 SQL 查詢回傳任何結果 (rows),測試就判定為失敗 (Fail)。 也就是說,測試是用來「抓出錯誤資料」的。

dbt 提供了兩種類型的測試:Generic Tests 與 Singular Tests。

Generic Tests (通用測試)

Generic Tests 是 dbt 內建的標準測試模組,定義在 YAML 檔案中。包含以下四種:

  • unique: 檢查欄位值是否唯一 (Primary Key 檢查)。
  • not_null: 檢查欄位值是否為非空。
  • accepted_values: 檢查欄位值是否在允許的清單內 (如 status 只能是 active, inactive)。
  • relationships: 檢查外鍵關聯 (Referential Integrity),確認 A 表的 key 是否存在於 B 表中。

如何設定

models/ 下的 YAML 檔案中 (如 schema.yml) 設定:

version: 2

models:
  - name: customers
    columns:
      - name: id
        tests:
          - unique
          - not_null

      - name: status
        tests:
          - accepted_values:
              values: ['active', 'inactive', 'deleted']

  - name: orders
    columns:
      - name: customer_id
        tests:
          - relationships:
              to: ref('customers')
              field: id

Singular Tests (單一測試)

當內建的通用測試不滿足需求,你需要針對特定的業務邏輯寫測試時 (例如:訂單金額不能為負數),就可以使用 Singular Tests。

如何建立

Singular Test 本質上就是一個放在 tests/ 目錄下的 .sql 檔案。

範例:建立 tests/assert_order_amount_is_positive.sql

-- 找出金額小於 0 的異常訂單
select
    order_id,
    amount
from {{ ref('orders') }}
where amount < 0

如果這個 SQL 查詢回傳了任何資料 (例如發現了一筆 -100 元的訂單),dbt test 就會報錯。

執行測試

使用以下指令執行所有測試:

dbt test

dbt 會依序執行所有定義好的 Generic Tests 和 Singular Tests,並告訴你 Pass 或 Fail。

常見參數

  • 選定特定 model 測試:dbt test --select customers
  • 選定特定測試類型:dbt test --select test_type:generic

總結

測試是 dbt 專案中不可或缺的一環。強烈建議為每一個 model 的 Primary Key 加上 uniquenot_null 測試,這是一個成本極低但效益極高的最佳實踐。