測試全綠,但 terminal 裡滿是紅色的 console.error。這種情況很常見,也很容易被忽略——畢竟測試過了嘛。但這些 error 不是憑空冒出來的,它們代表某個地方出了問題,只是沒人在乎。
vitest-fail-on-console 做的事很簡單:只要測試裡出現 console.error 或 console.warn,就讓那個測試失敗。強迫你正視這些訊息,而不是讓它們淹沒在輸出裡。
為什麼 console.error 出現在測試裡是壞味道
Vitest 預設不管 console 輸出。你可以在測試裡瘋狂 console.error,測試照樣過。
問題是:console.error 通常不是無意義的。它可能是:
- React 的 prop type 警告
- 某個 async 操作的錯誤被 catch 住但沒有妥善處理
- 第三方套件在告訴你用法錯了
- 自己程式裡某個 error handler 被觸發了
這些訊息出現在測試裡,代表測試在一個「有點不對勁」的狀態下執行,只是剛好沒有 throw 出來。隨著時間累積,測試輸出變成一片噪音,真正重要的訊息被淹沒,沒人再看了。
vitest-fail-on-console 把這個問題翻面:讓 console 訊息變成測試失敗,你才會被迫去處理它。
安裝
| |
設定
在 setup 檔案裡引入並呼叫:
| |
然後在 vitest.config.ts 裡把這個 setup 檔掛上去:
| |
就這樣。之後只要有測試裡出現 console.error 或 console.warn,那個測試就會失敗。
選項說明
failOnConsole() 接受一個選項物件,可以調整哪些 console 方法會觸發失敗:
| |
通常只需要管 error 和 warn,log / info / debug 視專案習慣決定要不要也納進來。
allowMessage
允許特定訊息通過,不觸發失敗。適合那種「已知會出現、暫時無法修」的訊息:
| |
silenceMessage
跟 allowMessage 類似,但連 console 輸出也一起隱藏,輸出更乾淨:
| |
skipTest
跳過特定測試檔或測試名稱,整個測試不套用 fail-on-console:
| |
afterEachDelay
有時候 async 操作的 console 呼叫會在測試結束後才執行,這個選項讓套件等一段時間再檢查:
| |
預期的 console.error 怎麼處理
裝了 vitest-fail-on-console 之後,如果某個測試就是要驗證「出現 error 時會呼叫 console.error」,直接讓它出現會讓測試失敗。
正確做法是用 vi.spyOn 把 console.error mock 掉,測試結束後就不會觸發 fail-on-console:
| |
這個寫法同時達到兩件事:測試明確說「我知道這裡會有 error」,而且斷言了 error 的內容。比讓 console.error 默默出現要嚴謹得多。
搭配乾淨測試環境一起用
vitest-fail-on-console 只處理 console 輸出的問題。如果你的測試還有 I/O 邊界需要替換(檔案系統、file watcher),可以搭配 memfs 一起用——思路是一樣的:讓測試環境的每個面向都在你的掌控之內。
相關做法可以參考 用 memfs + FakeWatchService 測試檔案系統。
