iT邦幫忙

2026 iThome 鐵人賽

DAY 14
0
Software Development

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

Day 14:一支被 skip() 掉的登入測試——測試覆蓋率數字 vs 實際保護力落差

  • 分享至 

  • xImage
  •  

前言

「這支功能有寫測試,而且測試都是綠燈,應該可以放心吧?」

這句話聽起來很合理,但今天要拆一個真實案例,證明這個推論不一定成立。這個系統的登入功能確實「有測試」,執行起來也確實「全部通過」,但打開測試內容之後會發現,真正涉及帳密驗證跟單一登入(SSO)流程的測試案例,整支被標記成跳過(skip),從來沒有真的執行過。

今日目標

  • 看一個「測試檔案存在、測試綠燈」但保護力其實很薄弱的真實案例
  • 理解 skip() 在真實專案裡代表什麼,為什麼團隊會選擇跳過而不是刪掉
  • 建立一個習慣:看到測試檔案,先問「這支測試實際驗證了什麼」,不要只看有沒有紅燈

一支只驗證「路由存在」的登入測試

這個系統的前台登入功能,對應的測試檔案只有一個測試案例,內容大致是這樣:發一個請求到登入端點,斷言回應的狀態碼不是 404。這支測試能抓到的問題,只有「這個路由被誰不小心刪掉了」這一種情況——真正的登入邏輯,包含帳號密碼驗證是否正確、驗證失敗時有沒有正確擋下、驗證成功後有沒有正確建立 session,這支測試完全沒有碰到。

而後台 Filament 登入頁面那邊,情況更值得注意:確實有一個測試案例在驗證單一登入(SSO)完整流程,斷言了正確的帳密能不能成功登入。但這個測試案例整支被標記成跳過,執行測試套件的時候會顯示「這個測試存在」,但實際上一行斷言都沒有真的跑過。

兩種角度看同一份測試結果

只看測試檔案存不存在、有沒有通過

$ php artisan test --filter=LoginTest
✓ login endpoint exists
1 passed

畫面上看到「1 passed」,直覺會覺得登入功能有測試覆蓋,而且測試是綠燈,狀況良好。

看測試實際涵蓋了哪些案例、有沒有被跳過的項目

$ php artisan test --filter=LoginTest -v
✓ login endpoint exists(淺層:只驗證路由可達)
- sso login flow with valid credentials (SKIPPED)
- sso login flow with invalid credentials (SKIPPED)

-v 印出完整清單之後,畫面完全不一樣:真正重要的兩個案例都在跳過清單裡,唯一真的跑過的那一個,驗證的只是「這個網址還連得到」,跟「登入功能對不對」幾乎沒有關係。

為什麼會有測試被 skip 而不是直接刪掉

這種情況在真實專案裡並不罕見。SSO 整合測試通常依賴外部系統(這裡是學校既有的校務系統)的實際回應行為,如果測試環境沒辦法穩定模擬這個外部依賴、或者這個依賴本身變動頻繁導致測試容易無故失敗,團隊有時候會選擇先跳過,而不是把測試刪掉——刪掉會讓「這裡本來該測什麼」這件事徹底消失,跳過至少留下了紀錄,讓後面接手的人知道這裡欠了一筆帳,只是還沒還。

代價很直接:這個路徑目前沒有任何自動化的安全網。如果哪次改動不小心讓 SSO 登入流程壞掉,測試套件不會告訴你,因為那個本來該告訴你的測試,根本沒有真的執行。

今日重點回顧

  • 這個系統的前台登入測試只驗證「路由存在」,不驗證實際登入行為
  • 後台 SSO 登入測試存在,但整支被 skip(),執行測試套件時不會真的跑到
  • 測試被跳過而不是刪掉,通常是團隊在「外部依賴不穩定」跟「保留待辦紀錄」之間的取捨
  • 看到測試結果顯示「通過」,要進一步確認:這支測試實際驗證了什麼,有沒有被跳過的重要案例

今日思考題

如果你現在打開手上專案的測試套件,用 -v 印出完整清單,會不會發現幾支被跳過、卻沒有人記得為什麼跳過的測試?這些跳過的案例,原本應該保護的是哪一段程式碼?

明日預告

明天要換一個角度:同一支類別要吃三種舊系統遺留下來的資料格式,怎麼用 dataset 一次把這些變形都測到,而不是複製貼上寫三支幾乎一樣的測試。


上一篇
Day 13:表單與表格測試分離——跟著架構重構一起發生的測試結構調整
系列文
同一套 Laravel 系統,測試怎麼寫才不會說謊14
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言