iT邦幫忙

2026 iThome 鐵人賽

DAY 27
0
Software Development

下載器不是寫完就能跑:一個 HLS 分段式串流工具的架構與測試修練系列 第 27 篇

Day 27:案例——一個看似綠燈的測試,其實沒斷言到真正關鍵的行為

  • 分享至 

  • xImage
  •  

前言:測試綠燈,代表邏輯是對的嗎?

測試綠燈只代表「斷言的部分都成立」,不代表「這段邏輯所有重要的行為都被驗證過」。如果斷言本身斷得不夠精準,一段邏輯即使被改壞了,測試依然會綠燈——這種假陽性測試比完全沒有測試更危險,因為它給了一種「有測試保護」的錯覺。

今日目標

  • 看一個常見的假陽性測試模式,套用在這個系列的下載驗證邏輯上
  • 理解「測試有跑到這段程式碼」跟「測試驗證了這段程式碼的行為」是兩回事
  • 學會怎麼檢查一個測試斷言是不是真的斷到重點

❌ vs ✅:斷言存在 vs 斷言到重點

以 Day 20 講過的「合併前驗證片段數量」邏輯為例:

❌ 反例:斷言只確認「沒有拋例外」

async def test_merge_with_complete_segments():
    await process(segments=make_segments(3), directory='video/item')
    # 測試跑完沒有拋例外,就當作「驗證通過」

這個測試只驗證了「正常情況下不會出錯」,但完全沒有驗證「數量不吻合時真的會被攔下來」——如果 Day 20 的驗證邏輯被不小心刪掉或改壞,這個測試依然會綠燈,因為它從來沒有測過「應該失敗」的情況。

✅ 正例:明確斷言「該失敗的情況真的會失敗」

async def test_merge_raises_when_segments_incomplete():
    with pytest.raises(IncompleteDownloadError):
        await process(segments=make_segments(3), directory='video/incomplete-item')
    # 明確驗證:片段不完整時,一定會拋出這個例外,不會被悄悄放行

怎麼檢查一個斷言是不是真的斷到重點

一個實用的檢查方法:故意把被測試的邏輯改壞(例如刪掉驗證那一行),看看測試會不會失敗。如果測試依然綠燈,代表這個測試沒有真的驗證到那段邏輯的行為,只是「跑過去了」而已。這個技巧有個正式名稱叫「突變測試」(mutation testing),概念上就是刻意注入錯誤,反過來檢驗測試本身有沒有能力抓到這個錯誤。

假陽性測試的根源:只驗證「happy path 沒出錯」

回顧這個模式的根源,通常是測試只涵蓋了「正常情況下程式能跑完」,卻沒有反過來驗證「異常情況下程式真的會如預期般失敗或攔下問題」。一段防禦性邏輯(驗證、例外拋出、fail fast)如果沒有對應的測試去驗證「它真的會在該發生作用的時候發生作用」,這段防禦性邏輯本身其實跟不存在沒有太大差別。

今日思考題

挑一段你寫過的防禦性邏輯(驗證、例外處理),試著故意把它改壞,看看對應的測試會不會真的失敗。如果不會,這個測試斷言到了什麼?

今日重點回顧

  • 測試綠燈只代表「斷言的部分成立」,不代表所有重要行為都被驗證過
  • 檢查斷言是否斷到重點的方法:故意改壞邏輯,看測試會不會失敗
  • 假陽性測試常見的根源:只驗證正常情況,沒驗證「異常情況真的會被攔下來」

明日預告

明天講測試替身選錯層的問題:mock 太底層,改一次實作就要改一次測試。


上一篇
Day 26:固定資料(fixture)要多真實——全真實內容 vs 只留測試需要的片段
下一篇
Day 28:測試替身選錯層——mock 太底層,改一次實作就要改一次測試
系列文
下載器不是寫完就能跑:一個 HLS 分段式串流工具的架構與測試修練 共 30 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言