iT邦幫忙

2024 iThome 鐵人賽

DAY 25
0
DevOps

我獨自升級:從水管工走向 DataOps系列 第 25

【Day 25】Data Pipeline 測試 - Data Quality feat. dbt test

  • 分享至 

  • xImage
  •  

前言

在談 dbt 的那幾天有稍微講到相關的測試,今天在繼續聊一聊有哪些測試可以做,如果還沒看前面的 dbt 說明,可以從下方連結過去/images/emoticon/emoticon12.gif

DBT 經典案例 Jaffle Shop (2) - 轉換步驟指南

DBT Test 是什麼?

簡單來說就是 DBT (Data Build Tool) 裡的一個測試資料品質的功能,確保數據轉換過程的準確性、一致性和完整性,優點有哪些:

  • 數據可靠性 upup
  • 自動化萬歲
  • 測試自動化了,開發和部署自然就快了
  • 減少人為錯誤
  • 大家都能看懂測試,團隊合作 code review 也會變快

不同測試的範例

1. 通用測試 (Generic Tests)

DBT 預設有四種通用測試:

  • Unique: 確保欄位內容都是唯一值。
  • Not Null: 檢查是否有空值。
  • Accepted Values: 看看值是否在我們允許範圍內。
  • Relationships: 檢查不同表之間的關係是否正確。

可以直接在 schema.yml 文件中設定

models:
  - name: customers
    columns:
      - name: customer_id
        tests:
          - unique
          - not_null
      - name: customer_type
        tests:
          - accepted_values:
              values: ['level1', 'level2', 'vip']

2. 單一測試 (Singular Tests)

單一測試是自訂的 SQL 查詢,用於檢查特定的業務邏輯或條件,通常放在 tests 目錄下

-- tests/assert_total_payments_positive.sql
SELECT
    order_id,
    SUM(amount) as total_amount
FROM {{ ref('payments') }}
GROUP BY 1
HAVING total_amount < 0

這個測試就是在判斷訂單總金額不能是負的

3. 自訂(通用)測試

可以創造自己的通用測試,例如檢查偶數的測試:

-- macros/test_is_even.sql
{% test is_even(model, column_name) %}
SELECT *
FROM {{ model }}
WHERE {{ column_name }} % 2 != 0
{% endtest %}

Q:還記得 macros 資料夾嗎?
A:macros 資料夾中會放可重複使用的程式碼片段或函數,讓你能夠在 SQL 查詢中使用類似程式語言的邏輯,提高了 SQL 的靈活性和避免過多重複內容。

然後在 schema.yml 中直接使用 is_even:

models:
  - name: even_numbers
    columns:
      - name: number
        tests:
          - is_even

4. 複雜測試範例

{% call statement('create_temp_table', fetch_result=True) %}
  CREATE TEMP TABLE temp_results AS (
    SELECT 
      o.order_id,
      o.total_amount,
      SUM(oi.quantity * oi.unit_price) as calculated_total,
      CASE 
        WHEN o.total_amount != SUM(oi.quantity * oi.unit_price) THEN true
        ELSE false
      END as test_failed
    FROM orders o
    JOIN order_items oi ON o.order_id = oi.order_id
    GROUP BY o.order_id, o.total_amount
  )
{% endcall %}

SELECT * FROM temp_results WHERE test_failed = true

這個範例檢查每個訂單的總金額是否與訂單項目的總和相同。如果不相同,test_failed 會被標記為 true。

透過創建臨時表 temp_results 讓測試更好管理,測試如果更複雜的話,用臨時表也會更好懂

執行 DBT Test

dbt test

如果只想跑特定類型的測試

dbt test --select test_type:generic
dbt test --select test_type:singular

測試失敗怎麼辦?

測試失敗是再正常不過,完全沒失敗比較可怕,因為正式上線可能就會阿伯~初四了/images/emoticon/emoticon06.gif

  1. 基本錯誤: 仔細看錯誤信息,檢查一下相關的模型和數據,除了真的開發中寫錯,很多時候都是業務邏輯和實際的資料有很多出入,很多預期外的資料範圍,就是你的資料不是你的資料/images/emoticon/emoticon02.gif
  2. 性能問題: 對於大型資料集,測試遇到性能問題,考慮使用抽樣測試或優化 SQL 查詢,通常測試站是正式的抽樣,例如取 1/10 的資料量,但是就需要另外定義,什麼樣的資料範圍可以較具代表性,不然該測的都沒測到
  3. 依賴關係: 確保測試的執行順序正確,特別是對於多個模型彼此依賴的測試

測試以外應該要知道...

  • 測試覆蓋率(Test coverage): 確保所有關鍵模型和欄位都有對應的測試
  • 測試要分類: 可以用標籤 (tags) 分類測試
  • 測試要有文件: 複雜的測試一定要加註解和文件說明,不然一個月後一定忘
  • 測試要整合進 CI/CD
  • 測試要定期檢查和更新: 養成改 data pipeline 就檢查測試的習慣

結語

今天就先這樣吧,有機會再說如何用dbt_utils做測試,明天會先介紹 《遠大前程》(Great Expectations) 的測試~


上一篇
【Day 24】Data Pipeline 測試 - Python linter feat. Ruff
下一篇
【Day 26】Data Pipeline 測試 - Data Quality feat. Great Expectations
系列文
我獨自升級:從水管工走向 DataOps30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言