「這段邏輯的單元測試寫得很仔細,代表這個功能整體是安全的嗎?」
今天要看的這支測試,品質其實不差——針對單一登入(SSO)底層元件的驗證相當完整。但如果把它跟 Day 14 那支被跳過的登入測試放在一起看,會得到一個不太舒服的結論:測試覆蓋率不能只看「有沒有測試檔案」,要看「測試涵蓋的是哪一層」。
這個系統負責跟外部校務系統對接單一登入的 Client 類別,有兩個測試案例分別驗證「學生帳號登入」跟「職員帳號登入」兩種情境——各自建構一個登入請求物件、直接呼叫 Client 的登入方法,斷言回傳的結果物件裡帶有預期的 session token 欄位。這兩支測試延續 Day 18 講的手法:注入測試替身、驗證回傳結構,寫得乾淨、範圍明確、不依賴真實外部連線。
單獨看這兩支測試,會覺得「SSO 登入這段邏輯測得很紮實」——而這個判斷,在「底層 SOAP 通訊協議正不正確」這個範圍內,是成立的。
❌ 只看底層元件測試,以為整個 SSO 功能都有保護
$ php artisan test --filter=SsoServiceClientTest
✓ student login returns session token
✓ staff login returns session token
2 passed
看到這兩支測試都是綠燈,很容易推論「這個系統的 SSO 登入功能應該沒問題」——但這個推論跳過了一個關鍵問題:這兩支測試驗證的是「SOAP Client 這一層,跟外部系統的溝通協議對不對」,不是「使用者從瀏覽器點登入到真的登入成功,中間這整條路徑對不對」。
✅ 對照 Day 14 的整合測試狀態,看清楚保護的範圍
底層:tests/Unit/ECampus/Soap/SsoServiceClientTest.php
✓ 學生登入、職員登入,SOAP 協議層驗證完整
整合:tests/Feature/Filament/Pages/Auth/LoginTest.php
- sso login flow with valid credentials (SKIPPED)
- sso login flow with invalid credentials (SKIPPED)
把兩層並排看,畫面立刻不一樣:底層通訊協議測得很仔細,但「使用者在登入頁面輸入帳密、系統呼叫 SSO、驗證結果、建立對應的使用者 session」這整條串起來的路徑,對應的整合測試整支被跳過。中間這一段——把底層 Client 的結果轉換成使用者實際的登入狀態——沒有任何自動化測試在保護。
如果只看「這個系統有沒有 SSO 相關的測試」,答案是有,而且看起來寫得不錯。但如果問的是「如果 SSO 整合流程壞了,會不會有測試立刻變紅」,答案是不會——因為真正涵蓋整合路徑的那支測試,從來沒有真的執行過。這正是這個系列從 Day 1 開始就在強調的核心命題:測試檔案存在、測試綠燈,都只是保護力的必要條件,不是充分條件,真正要問的問題永遠是「這裡的邏輯壞了,有沒有一個測試會因此變紅」。
底層元件測得仔細不是壞事,這代表至少「跟外部系統溝通的協議格式對不對」這一層是有安全網的。問題在於,如果只看到這一層測試齊全,就誤以為整個功能都有保護,反而會掩蓋掉真正的風險缺口。
回想你手上專案裡任何一個「底層元件測得很仔細」的功能,往上一層的整合路徑,有沒有對應的測試?如果沒有,你有多確定「底層測過」等於「整個功能是安全的」?
明天要誠實面對一支目前只涵蓋 happy path 的爬蟲測試——只驗證正常情況,代表什麼樣的風險還沒被涵蓋到。