博客 / 詳情

返回

【總結整理】軟件測試的反模式

最近看到一篇介紹軟件測試相關的文章,文章雖然比較早(2018年的),但是其中的觀點依然適用。

在目前AI盛行的時候,軟件測試也必然迎來它的變化。

我把文章中的要點整理了一下,這些測試的反模式涵蓋了從測試策略、代碼質量到心態管理的各個方面。

原文的鏈接放在了文章的末尾。

1. 只有單元測試,沒有集成測試 (Having unit tests without integration tests)

  • 問題:即使所有獨立的類/方法都通過了測試,但在實際運行時,組件之間的連接(數據庫、網絡、外部API)可能會失敗。
  • 盲點:單元測試無法覆蓋跨切面關注點(Cross-cutting concerns),如事務處理、SQL觸發器、API契約不匹配等。
  • 建議:除非是完全隔離的工具(如命令行計算器),否則必須引入集成測試來驗證系統各部分的協作。

2. 只有集成測試,沒有單元測試 (Having integration tests without unit tests)

  • 問題:通常由認為“單元測試沒用”的開發者造成。
  • 代價
    • 複雜度爆炸:要覆蓋所有代碼路徑的組合,集成測試的數量會呈指數級增長,難以維護。
    • 執行極慢:反饋循環太長(從幾秒變為幾分鐘甚至更久),降低開發效率。
    • 調試困難:測試失敗時,難以快速定位是哪個組件出了問題。
  • 建議:遵循測試金字塔,用大量單元測試覆蓋業務邏輯,用少量集成測試覆蓋組件交互。

3. 只有錯誤類型的測試 (Having the wrong kind of tests)

  • 問題:盲目照搬“測試金字塔”,而不考慮應用的實際類型。
  • 場景區分
    • 計算型工具(如Linux命令):應以單元測試為主。
    • 支付網關(重外部交互):應以集成測試為主。
    • 網站生成器(重交互體驗):應以UI測試為主。
  • 要點:根據業務價值決定測試類型,而不是死守一種形狀。

4. 測試錯誤的功能 (Testing the wrong functionality)

  • 問題:為了追求覆蓋率而測試無關緊要的代碼(如簡單的 Getter/Setter),卻忽視了核心風險。
  • 策略:建立“代碼嚴重性”心理模型:
    • 關鍵代碼 (Critical):經常變更、經常出錯、業務影響大 -> 必須覆蓋
    • 核心代碼 (Core):偶爾變更 -> 儘量覆蓋。
    • 其他代碼 (Other):幾乎不變 -> 沒必要浪費時間。
  • 建議:優先覆蓋那 20% 導致 80% 問題的關鍵代碼。

5. 測試內部實現細節 (Testing internal implementation)

  • 問題:測試與代碼的實現方式緊密耦合,而不是驗證行為
  • 後果:重構代碼(Refactoring)時,即使業務邏輯沒變,測試也會報錯。這會導致開發者認為“測試是累贅”。
  • 建議:測試應該關注輸入和輸出(行為),而非對象內部的狀態或私有字段。

6. 過度關注代碼覆蓋率 (Paying excessive attention to test coverage)

  • 問題:將覆蓋率(如 100%)視為唯一的質量指標,導致出現大量為了刷數據的低質量測試。
  • 觀點:覆蓋率只是一個參考數字。高覆蓋率不代表無 Bug。
  • 更好的指標
    • PDWT:寫測試的開發人員百分比(應為100%)。
    • PBCNT:生產環境 Bug 轉化為新測試的百分比。
    • PTD:確定性(非不穩定)測試的百分比。

7. 擁有不穩定或緩慢的測試 (Having flaky or slow tests)

  • 問題:測試時過時掛(Flaky),導致團隊失去信任,忽略測試結果。
  • 來源:通常是集成測試或 UI 測試,源於環境不穩或異步處理不當。
  • 建議:必須修復或隔離不穩定測試。測試套件必須是絕對可靠(Deterministic)的,任何失敗都應代表真實的代碼問題。

8. 手動運行測試 (Running tests manually)

  • 問題:依賴人工觸發測試或人工準備環境,無法實現真正的 CI/CD。
  • 目標:所有與代碼正確性相關的測試(單元/集成)必須完全自動化。
  • 標準:開發者提交代碼後,應在 5-15 分鐘內自動獲得反饋。QA 應專注於設計新測試,而不是充當“測試運行器”。

9. 將測試代碼視為二等公民 (Treating test code as a second class citizen)

  • 問題:生產代碼寫得很漂亮,測試代碼卻充滿了複製粘貼、硬編碼和糟糕的設計。
  • 後果:測試代碼難以維護,修改成本高昂,最終被拋棄。
  • 建議:對測試代碼應用同樣的工程標準(DRY, KISS, SOLID)。重構測試代碼,提取公共庫及 Helper 方法。

10. 不將生產環境 Bug 轉化為測試 (Not converting production bugs to tests)

  • 問題:修復了 Bug 但未添加回歸測試,導致同樣的問題在未來重複出現。
  • 價值:源自生產環境的 Bug 測試價值極高,因為它們直接對應了真實世界的痛點和高風險區域。
  • 規則:每一個線上 Bug 的修復,都必須伴隨一個能復現該 Bug 的測試用例。

11. 將 TDD 奉為宗教 (Treating TDD as a religion)

  • 問題:教條式地要求所有代碼都必須“先寫測試再寫實現”。
  • 現實:在探索性編程(Spike)、原型設計或極早期初創階段,後補測試或不寫測試也是合理的策略。
  • 建議:TDD 是一個好工具,但不是唯一的真理。根據項目階段和需求清晰度靈活選擇。

12. 寫測試不看文檔 (Writing tests without reading documentation first)

  • 問題:因為不熟悉測試框架,自己造輪子寫各種笨拙的“工具方法”。
  • 後果:測試代碼晦澀難懂,非標準化的寫法增加了新人的學習成本。
  • 建議:深入學習測試框架的功能(如參數化測試、Mock 工具、Setup/Teardown 機制),使用標準庫而非自制土方。

13. 因無知而敗壞測試的名聲 (Giving testing a bad reputation out of ignorance)

  • 問題:開發者因為經歷過上述反模式(如經歷過極慢的測試、脆弱的測試),從而徹底否定測試的價值。
  • 觀點:不要因為錯誤的測試方式(Bad Habits)而否定測試本身。
  • 建議:識別並承認過去糟糕的測試體驗是由於“反模式”造成的,在新項目中採用正確的實踐。

原文章來源:Software Testing Anti-patterns

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.