現代軟件應用由眾多動態組件構成,這些組件會同時生成、收集並相互拉取數據。一旦其中任一組件出現異常行為,甚至發生故障,就可能對其依賴的其他組件產生連鎖反應。
依據軟件本身的性質,這類錯誤或故障可能導致系統停機、經濟損失、基礎設施崩潰、安全隱患,甚至危及生命。因此我們需要對軟件進行測試與監控。沿着軟件生命週期在恰當的階段、採用合適的方法與用例進行測試,能更早、更高概率地在用户之前發現問題。
When 與 Where 進行測試
一般而言,測試發生在軟件開發生命週期(SDLC)中的測試階段。但對於某些測試類型,並非如此——不同測試的實施與運行時機會有差異。在討論如何選擇合適的測試之前,我們先快速回顧一下不同測試類型的適用時機與位置。
常見測試類型
下表為工程化測試矩陣,按測試類型、識別問題、所處 SDLC 階段與實施方式進行分層梳理,可作為選型與階段規劃的“總覽圖”與協同基準。
| 測試類型 | 識別問題 | 所處階段(SDLC) | 實施方式 |
|---|---|---|---|
| 單元 | 意外或缺失的函數輸入與輸出 | 開發、測試 | 在代碼中定義,通常由語言庫提供 |
| API 與集成 | 與第三方服務的集成問題 | 開發、部署、測試 | 在代碼中定義,通常結合語言與相關集成庫 |
| UI | 用户界面中的功能交互 | 測試 | 專用測試框架 |
| 安全 | **向量 | 開發、測試、部署、運維 | 專用測試框架 |
| 性能 | 關鍵應用指標 | 部署、運維 | 取決於指標的工具 |
| 冒煙 | 構建後應用是否仍能工作 | 測試、部署 | 專用測試框架 |
| 迴歸 | 新代碼是否破壞既有功能 | 測試、部署 | 專用測試框架 |
如何使用測試矩陣
使用矩陣做測試決策時,優先考慮以下維度:風險、反饋速度、變更範圍、環境約束與成本、團隊所有權。
- 業務與用户風險:影響面越廣、頻率越高,優先級越高(UI 關鍵路徑、迴歸集合優先)。
- 變更類型:純業務邏輯→單元;跨邊界集成→API/集成;可視交互→UI。
- 反饋速度 vs 覆蓋面:單元最快、成本最低;迴歸最慢、覆蓋最廣,按風險分層執行。
- 環境與數據依賴:能模擬就模擬,必要時才使用真環境與真實數據,控制不穩定因素。
- 所有權與協作:開發主導單元/契約,測試主導 UI/迴歸,平台/安全負責掃描與門禁。
按類型的觸發器與執行要點:
- 單元測試:新增或重構函數/類;修復過的缺陷用例固化;邊界條件與異常分支;純算法與數據轉換邏輯。
- API 與集成測試:接口/認證變更;第三方版本升級;限流/超時/重試策略;契約(Pact 等)作為合併門禁。
- UI 測試:登錄、搜索、下單等關鍵用户路徑;多端一致性;高易碎交互(拖拽、虛擬列表、複雜表單)。
- 安全測試:新增依賴或配置變更;外部暴露面擴大;CI 定期依賴與鏡像掃描,發佈前高危阻斷。
- 性能測試:新功能觸達熱點路徑;QPS/延遲/錯誤率目標;容量評估與基線迴歸;關鍵事務的 SLO 校驗。
- 冒煙測試:每次構建與部署前後;服務與核心能力可用性檢查;失敗立即回滾或阻斷後續流程。
- 迴歸測試:版本發版前;高風險合併;跨模塊改動;按“核心路徑→高風險場景→長尾用例”分層執行。
執行原則:左移優先、分層防護、契約優先於端到端、金絲雀+冒煙、監控閉環到問題覆盤。
示例應用
我有一個正在從副項目逐步成長為完整應用的想法:一個待辦聚合器。它會從多個外部服務拉取分配給我的任務,並將其彙總到一個更易瀏覽的列表中。應用通過各服務的 API 獲取任務數據,用户可以對列表進行排序與篩選,並點擊列表項查看任務詳情。應用基於 TypeScript 與 React 開發,使用了 Material UI;同時還通過 React Native 提供了移動端與桌面端版本。
必備測試
除非有充分理由不納入,本節所述測試通常都應該包含在應用的測試套件中。
單元測試
幾乎所有應用都需要單元測試,且可以在編寫代碼時同步創建。只要應用包含一個以上具備功能性的組件,就應當配套單元測試。示例應用中有一個組件負責將 API 返回的數據轉換為可在 UI 中渲染的 React 對象。
由於應用使用 TypeScript,可用於編寫單元測試的選擇很多,包括 Jest、Mocha 與 Jasmine。它們各有優劣,沒有絕對的完美答案。Jest 目前可能更受歡迎,由 Facebook 創建用於測試 React。示例應用基於 React,自然契合。
API 與集成測試
示例應用高度依賴多個 API,這些 API 存在多種潛在故障點,處理不當就可能導致應用不可用。API 測試與集成測試並不完全相同:API 測試只關注 API 交互;集成測試可以包含 API 測試,也可能覆蓋其他第三方集成,如外部組件。由於本例唯一的第三方集成是 API,我們可以將二者等同處理。
API 測試通常在應用代碼之外執行,使用外部工具或在 CI 流水線中進行。開源選擇包括自行編寫調用 API 端點的測試、SoapUI(由制定 API 規範標準的團隊出品)、Pact 與 Dredd。就我個人而言,常在 CI 中使用 Dredd,但 API 測試並沒有唯一的正確選擇。
UI 測試
凡是有可視化前端的應用,都需要自動化 UI 測試。此類測試通常會模擬界面交互,以驗證其按預期工作。示例應用的 UI 簡潔但對用户體驗至關重要。
UI 自動化測試通常手動運行,或集成到 CI 流程中。幸運的是,成熟工具非常多,有的獨立於編程語言,有的與語言生態綁定。如果你的應用是 Web 應用,這些工具通常使用無頭瀏覽器在不可見的環境中執行測試;若是某種原生應用,則可選工具會有所不同。
可選測試
本節介紹在資源允許的情況下可以納入的測試類型,它們有助於提升應用的穩定性與整體用户體驗。
安全
安全問題比以往任何時候都更值得重視。你需要在開發階段檢查潛在的脆弱代碼,同時關注依賴引入的新型供應鏈安全風險。除了測試之外,基於供應鏈管理需要對外部包進行生成清單與維護管理的需求正在快速增長,相關的合規監管也可能很快到來。用於滿足上述需求的工具大致分為兩類:有的同時掃描你的自有代碼與外部依賴,有的只負責其中之一。
掃描是眾多 SaaS 廠商發力的新增長點,但也有一些流行的開源或免費選擇,例如 GitHub、Falco 與 Trivy。它們與編程語言無關,如何選擇主要取決於你應用背後的基礎設施。示例應用在用户本地設備運行,因此最合適的時機是在 CI/CD 構建過程中執行 檢查。
性能測試
如果沒有任何性能監控,再精巧的應用也可能在用户手中“掉鏈子”。與列表中多數在 SDLC 某些階段性運行的測試不同,性能測試通常是持續進行的。一些工具支持以模擬負載的方式仿真生產使用場景,但這仍與真實用户不同。
由於性能監控通常需要集中化服務來匯聚與分析數據,相關工具多為商業服務。但也有一些開源或免費選擇,例如 k6(用於模擬)、將 React <Profiler> 數據發送至類似 Grafana 的系統,以及 Lighthouse CI。
冒煙測試
許多測試方法關注的是單個功能或組件,而不是覆蓋用户實際使用時的關鍵路徑。冒煙測試通常在 QA 環境中驗證新構建的關鍵功能是否可用,然後再進入後續測試。冒煙測試可以由 QA 團隊手動執行,也可以使用自動化工具。選擇何種工具取決於你要測試的目標,本文提到的許多工具都能提供幫助。
迴歸測試
迴歸測試並非具體的一組工具,而是一種將其他測試進行分組的最佳實踐,目的是確保新功能不會對應用產生負面影響。比如,一個新版本增加了在聚合應用中修改任務狀態並回寫至來源任務的能力。下面這些測試將協同工作,以確保這個新功能不會影響既有的“僅用於查看聚合任務”的功能。
落地路徑:從 0 到 1 到持續優化
- 第 1 步(基線化):建立最小可用集合——關鍵模塊單元測試、核心 API 契約測試、部署冒煙清單。
- 第 2 步(CI 左移):PR 必跑單元+契約;主幹集成後自動冒煙;高危變更自動加嚴門禁。
- 第 3 步(迴歸分層):按風險分層(核心路徑→高風險→長尾),白天跑短集,夜間/預發跑全量。
- 第 4 步(可觀測性):度量延遲/錯誤率/吞吐;測試內埋點與追蹤關聯,問題可追溯。
- 第 5 步(持續治理):定義測試健康度(穩定性、去冗、覆蓋有效性);清理脆弱與重複用例;建立“測試債務”看板。
結語
本文梳理了應用可以實施的多種測試類型,以及它們能夠預防的問題。這些問題可能損害用户體驗、暴露安全風險,甚至導致用户不再願意使用你的應用或服務。每當你新增功能或對現有功能做出重大變更時,都應當編寫相應測試並儘可能頻繁地運行。在許多現代 SDLC 流程中,測試通常會在開發者將代碼提交到版本控制時自動運行,而你也應該保持高頻提交的節奏。