iT邦幫忙

2026 iThome 鐵人賽

DAY 20
0
Software Development

同一套 Laravel 系統,測試怎麼寫才不會說謊系列 第 20

Day 20:Crawler 測試——目前只有 happy path,這代表什麼風險

  • 分享至 

  • xImage
  •  

前言

「這段爬蟲邏輯有測試,是不是就代表它夠穩固了?」

今天要誠實面對一個沒那麼漂亮的案例。這個系統負責從外部網頁抓取新聞資料的 Crawler 類別,目前只有一個測試案例,而且只驗證了最順利的那條路徑——外部網頁格式正常、回應正常、抓到預期筆數的資料。真正會讓這種整合邏輯出問題的邊界情況,目前完全沒有被涵蓋到。這篇不是要示範「怎麼寫出完美的爬蟲測試」,而是要老實盤點現況、討論這代表什麼風險。

今日目標

  • 看這個系統目前唯一一支 Crawler 測試實際驗證了什麼
  • 誠實指出這支測試沒有涵蓋到的邊界情況
  • 理解「爬蟲類整合邏輯」為什麼特別容易停留在「先求有」階段
  • 建立習慣:看到測試覆蓋率數字,要進一步確認涵蓋的是正常情況還是異常情況

目前唯一的測試在驗證什麼

這個系統的 Crawler 類別,對應的測試檔案裡只有一個測試案例:用 Day 16 提到的測試替身搭配一份錄影帶,驗證呼叫抓取新聞的方法之後,回傳了預期筆數的資料。這支測試確實驗證了一件事——「當外部網頁回應格式正常時,這段程式碼能正確解析出資料」。這件事本身有價值,代表基本的解析邏輯是能運作的。

這支測試沒有回答的問題

只看測試通過,以為爬蟲邏輯夠穩固

$ php artisan test --filter=CrawlerTest
✓ fetch
1 passed

看到通過,很容易誤以為這段整合邏輯已經經過充分驗證。

列出這支測試實際涵蓋跟沒涵蓋的範圍

已涵蓋:外部網頁格式正常時,能正確解析出預期筆數的資料

未涵蓋:
- 外部網頁結構跟預期不一樣時(改版、欄位順序變動)會發生什麼
- 回應是空內容、或格式完全解析不出來時,程式碼會不會直接噴例外
- 部分資料缺漏(例如某幾筆新聞少了某個欄位)時的處理方式

列出來之後會發現,目前唯一驗證的是最理想的那一種情況,而爬蟲類整合邏輯真正容易出問題的地方,往往正是外部網頁「不如預期」的時候——這些情況目前完全沒有測試在把關。

為什麼這類邏輯容易停留在「先求有」階段

跟外部系統整合的邏輯,寫第一版測試的時候,最直覺的做法就是先錄一次正常運作的流量,證明「這段程式碼至少能處理正常情況」。這一步門檻低、容易完成,也確實提供了基本的信心。但要進一步涵蓋「外部系統回應格式異常時該怎麼辦」,需要先想清楚「異常會長什麼樣子」——這需要對外部系統的行為有更深的觀察,或者真的踩過一次線上事故才會知道要防什麼,門檻明顯更高。這正是為什麼這類整合測試容易停在「先求有」:先求有能建立基本信心,但往往就停在這裡,沒有人回頭補上異常情況的測試。

誠實面對這件事,比假裝已經涵蓋更有價值

這篇沒有示範「怎麼寫出完美涵蓋所有邊界情況的爬蟲測試」,因為這個系統目前確實還沒有做到。誠實承認「目前只有 happy path、邊界情況還沒涵蓋」,比宣稱這裡已經示範了完整的防禦,更貼近真實維護專案的樣子——測試覆蓋率的意義不只是「有沒有測試」,還包括「誠實知道現在測到哪裡、還缺什麼」,這份自知本身就是一種風險管理。

今日思考題

回想你手上專案裡任何一段跟外部系統整合的邏輯,測試涵蓋的是不是也只有「外部系統回應正常」這一種情況?如果外部系統哪天真的回應了一個你沒預期到的格式,你的程式碼會怎麼反應——這件事,你現在有把握回答嗎?

今日重點回顧

  • Crawler 測試目前只有一個案例,只驗證外部網頁格式正常時的解析行為
  • 外部系統回應格式異常、內容缺漏等邊界情況,目前完全沒有測試涵蓋
  • 整合類邏輯容易停留在「先求有」,因為驗證正常情況門檻低、驗證異常情況需要更深的觀察
  • 誠實盤點測試現況、承認還缺什麼,比宣稱已經涵蓋所有情況更有實際價值

明日預告

明天要看一支只用「症狀」驗證、不糾結內部實作細節的容錯測試——處理外部系統傳回的髒 XML 資料時,這種驗證方式為什麼反而更穩固。


上一篇
Day 19:SSO 登入的單元測試很紮實——但要跟 Day 14 對照著看
系列文
同一套 Laravel 系統,測試怎麼寫才不會說謊20
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言