前面章節已確認目標系統的功能、部署方式與跨服務互動。如果系統在單次操作時能正確回應,仍不能推論它在多項工作同時發生時可以維持相同結果。等待時間可能逐步增加,工作佇列可能持續累積,相依項目也可能在大量重試後失效。
效能測試要回答一個有條件的問題:在指定環境、資料規模、操作組合與持續時間下,系統能否在驗收門檻內完成工作,超過容量後又會如何失敗及恢復。這些條件缺少任何一項,「系統每秒可以處理多少工作」都只是一個無法重現的數字。
「回應要快」與「系統要能承受尖峰」沒有明確限制,無法決定測試負載、持續時間及通過標準。開始撰寫腳本前,應該先根據已核准需求記錄下列內容:
| 確認面向 | 要定義的條件 | 可檢查結果 |
|---|---|---|
| 工作負載 | 每秒操作數、同時執行數、操作比例、資料規模及持續時間 | 測試實際產生的負載符合指定範圍 |
| 回應時間 | 每類操作的平均值、第 95 與第 99 百分位限制 | 指定比例的操作在時間門檻內完成 |
| 吞吐量 | 單位時間內必須完成的有效工作數量 | 完成量達到需求,且沒有以大量錯誤換取表面數字 |
| 錯誤比例 | 可接受的逾時、拒絕及失敗比例 | 測試期間各類錯誤沒有超過個別門檻 |
| 資料結果 | 負載期間與測試後必須維持的功能及保存結果 | 已完成操作的輸出、狀態變化與外部效果通過驗證 |
| 積壓限制 | 佇列或待處理工作的數量與最長等待時間 | 積壓沒有持續成長,或能在限制時間內清除 |
| 恢復時間 | 負載下降或相依項目恢復後,多久要回到正常範圍 | 回應、錯誤與積壓在期限內恢復 |
吞吐量(Throughput)代表單位時間內完成的有效工作數量,不能只計算已送入系統的操作。接受工作後長期停留在佇列,或以錯誤結果快速結束,都不構成有效完成量。
效能基準記錄某個版本在固定條件下的結果,驗收門檻則來自目標需求。遺留系統的既有表現可以作為比較起點,但如果它本來就無法滿足需求,不能直接成為目標系統的通過標準。
測試情境要反映系統真正會執行的工作。可以從執行紀錄、排程、功能統計與已確認的使用方式整理一般時段、尖峰時段及特殊批次的操作組合:
如果目標系統包含既有系統沒有的新功能,就要按照已核准的預期使用量建立假設,記錄假設來源及重新評估條件。缺少歷史紀錄時,可以先測量多組範圍,不能把最有利的一組結果當成未來容量。
工作負載模型也要區分到達率與同時執行數。每秒進入十項工作,不代表系統同時只處理十項。當回應變慢,尚未完成的工作會增加,同時執行數也會跟著上升。兩者混用會讓測試在系統變慢時自動降低輸入,掩蓋真正的過載情況。
效能測試是涵蓋多種測試目的的上位概念。ISTQB 效能測試教材分別定義負載、壓力、尖峰與耐久等測試,每一種回答的問題不同。
| 測試類型 | 負載方式 | 要回答的問題 | 主要觀察結果 |
|---|---|---|---|
| 負載測試(Load Testing) | 在預期與尖峰範圍內逐步增加或維持工作量 | 系統能否在預定負載下持續符合驗收門檻 | 回應時間、吞吐量、錯誤比例、積壓與執行資源餘裕 |
| 壓力測試(Stress Testing) | 提高到預期範圍以上,直到門檻失守或觸發停止條件 | 容量上限在哪裡,超載時會如何失敗 | 最大穩定負載、第一個瓶頸、拒絕方式與恢復時間 |
| 尖峰測試(Spike Testing) | 在短時間內快速提高工作量,再降回正常範圍 | 突發工作是否造成失控積壓或連鎖失敗 | 瞬間錯誤、排隊時間、降級結果及恢復速度 |
| 耐久測試(Soak Testing) | 在代表性負載下持續執行符合實際情境的長時間 | 長時間運作是否出現累積性退化 | 資源持續成長、連線未釋放、垃圾回收停頓、積壓與效能漂移 |
四種測試可以共用功能流程與量測方式,但負載形狀、持續時間及通過條件要分開保存。短時間負載測試通過,不足以證明長時間穩定。壓力測試找到失敗點,也不表示預期負載已經通過驗收。
高負載測試可能耗用大量執行資源、產生保存資料,並且觸發相依項目的限制。預設應該在獨立環境執行,並使容量相關設定盡量接近預定部署環境:
如果測試環境的容量或拓撲與預定部署環境不同,結果只能代表目前環境。從縮小環境直接等比例推算正式容量,可能忽略共享限制、固定成本與非線性瓶頸,必須另外驗證推算方式。
正式環境中的有限測試只有在風險已核准、範圍可控制且具備停止條件時才能進行。測試前要限制對正式資料與其他使用對象的影響,並確認監控、通知及復原流程已經就緒。
測試腳本只描述如何執行,完整情境還要記錄輸入資料、負載階段、預期結果與停止條件。遺留系統和目標系統應該共用相同案例識別碼與比較格式。
| 情境欄位 | 應記錄的內容 |
|---|---|
| 案例識別碼 | 使用穩定名稱,例如 PERF-READ-01,讓兩套系統與歷次結果可以對照 |
| 功能流程 | 每一步輸入、等待、狀態相依及預期輸出 |
| 資料版本 | 測試資料集、初始狀態、資料量與重建方式 |
| 負載模型 | 到達率或同時執行數、操作比例及各階段持續時間 |
| 測試階段 | 腳本確認、暖機、逐步增加、穩定執行、降載及恢復觀察 |
| 驗收門檻 | 回應時間百分位、吞吐量、錯誤比例、積壓與資料正確性 |
| 停止條件 | 錯誤、等待、積壓或資源狀態達到何種程度時中止測試 |
暖機用來讓程式載入必要內容、建立連線並進入可比較狀態。暖機結果不應混入正式量測區間。測試是否採用已暖機或剛啟動狀態,取決於實際需求,兩者都需要時就分成不同案例。
輸入資料也要避免每次重複命中同一筆內容。可以按照已確認的熱門程度分布選取資料,並為會修改狀態的操作建立足夠且可重設的輸入,避免資料衝突改變原本要測量的處理路徑。
負載工具通常提供兩種排程觀念:k6 的工作負載模型說明與 Gatling 的模型說明都要求測試者按照系統實際接收工作的方式選擇。
工具中的 VU 代表一個重複執行情境的單元,不必然等於一位實際操作人員。腳本等待時間、操作長度與回應速度都會影響一個 VU 能完成多少工作,不能直接把 VU 數量當成每秒操作數。
如果實際工作會持續到達,封閉式模型在系統變慢時也會降低新工作的產生速度,形成協調遺漏(Coordinated Omission)。測試結果可能顯示負載穩定,實際上只是產生器跟著受測系統一起變慢。應該以開放式模型維持指定到達率,或另外記錄原本應該到達但未送出的工作。
工具選擇要根據受測互動方式、負載模型、腳本維護能力、結果格式與自動化需求。k6、Apache JMeter 與 Gatling 都能建立負載測試,使用方式與限制不同。
| 工具 | 腳本與模型 | 適合評估的情境 | 使用前要確認的限制 |
|---|---|---|---|
| k6 | 使用 JavaScript 或 TypeScript 描述情境,透過 Scenario 與 Executor 控制負載,並以 Threshold 定義通過條件 | 希望以程式碼維護協定層或瀏覽器情境,並將門檻納入自動執行 | TypeScript 執行時只移除型別資訊,不會提供完整型別檢查。大型測試也要驗證產生器容量與分散執行方式 |
| Apache JMeter | 以測試計畫樹組合取樣器、資料與判斷條件,圖形介面適合建立及除錯計畫 | 已有 JMX 測試計畫、需要其支援的協定或偏好圖形化建模 | 正式負載應使用命令列模式。大量監聽器與圖形介面會影響產生負載的能力 |
| Gatling | 支援 Java、JavaScript、TypeScript、Kotlin 與 Scala,提供開放式及封閉式注入模型與 Assertion | 希望使用程式語言、建置工具與程式碼審查維護情境 | 各語言 SDK、協定與社群版或企業版能力不同,選擇前要核對需要的協定、報表及分散執行方式 |
k6 的 Threshold 文件與 Gatling 的 Assertion 文件都能將回應時間、錯誤比例或其他統計值轉成通過與失敗結果。JMeter 官方手冊則明確要求正式負載使用命令列模式,圖形介面只用於建立及除錯測試計畫。
選擇前可以用一個代表性情境完成概念驗證(Proof of Concept, POC),比較腳本可讀性、資料準備、負載形狀、門檻判定、原始結果匯出及失敗調查。也要讓負載產生器執行到高於預期負載,確認限制來自受測系統,而非工具執行環境。
如果測試只在協定層直接送出操作,結果不包含瀏覽器呈現與互動時間。目標需求包含操作介面時,應該分開建立瀏覽器量測或少量混合情境,並保留各自的指標與門檻。k6 的網站負載測試說明也區分協定層、瀏覽器與混合測試的量測範圍。
負載工具看到的是操作開始到結果返回的時間,無法單獨指出等待發生在哪一段。測試期間要用相同時間範圍與案例識別碼,對照受測系統及相依項目的紀錄與指標。
| 觀察位置 | 建議記錄的指標 | 可以協助判斷的問題 |
|---|---|---|
| 負載產生器 | 實際到達率、同時執行數、成功與失敗數、回應時間及產生器餘裕 | 測試是否真的送出預定負載,產生器是否先受限 |
| 系統入口 | 接受、拒絕、逾時、排隊與執行時間 | 延遲來自等待、處理或超載保護 |
| 程式內部 | 各處理階段時間、工作佇列、連線池、垃圾回收與重試次數 | 哪一段開始飽和,重試是否放大負載 |
| 保存機制 | 讀寫等待、衝突、連線使用與慢操作 | 如果系統保存狀態,限制是否發生在保存邊界 |
| 相依項目 | 呼叫數、等待時間、錯誤、逾時與斷路狀態 | 效能問題是否由相依項目或錯誤重試造成 |
| 非同步流程 | 佇列深度、最舊工作等待時間、消費速率與重試數 | 對外操作完成後,後續工作是否持續落後 |
| 執行環境 | 執行資源使用率、限制與節流事件 | 目前設定是否已達容量限制 |
如果系統使用資料庫、訊息代理或跨程序呼叫,才加入相對應的連線、查詢、消費與通訊指標。通用測試清單不需要替每個系統預設這些構成。
測試結果應該使用 operationId 或案例標籤串連一次操作的負載資料、程式記錄與相依結果。只有各自獨立的平均值,很難判斷同一時間發生的延遲與錯誤是否相關。
平均回應時間會把少量極慢操作與大量快速操作混合,無法呈現大多數操作對延遲的實際感受。第 95 百分位(95th Percentile, p95)為 800 毫秒,表示量測樣本中有 95% 在 800 毫秒內完成,其餘 5% 較慢。第 99 百分位(99th Percentile, p99)則更接近長尾操作。
分析百分位數時要保持相同量測範圍:
最大值容易受到單一特殊事件影響,可以保留作為調查線索。驗收門檻通常應該使用與需求相符的百分位數、錯誤比例及完成量共同判斷。
容量上限要透過逐步增加負載觀察,不能只執行一次極高壓力。每一個負載階段都要持續足夠時間,讓排隊、重試、垃圾回收與相依限制有機會出現。
最大穩定負載是目前版本與設定在指定持續時間內,仍能通過回應、錯誤、完成量、積壓及正確性條件的最高已驗證負載。它不代表短時間曾經接受的最高數字,也不能直接套用到不同環境或資料規模。
正式運作的安全容量應該低於最大穩定負載。保留多少餘裕要考量工作量波動、資料成長、相依項目變化、擴充所需時間與故障期間可用容量,沒有適用所有系統的固定比例。安全容量、告警門檻與重新測試條件應該一起記錄。
壓力測試除了找到門檻,也要確認超過門檻後的行為可控制。系統可以按照設計拒絕、延後或降級工作,但不能在沒有明確結果的情況下遺失已接受的操作。
測試要預先設定中止條件,例如連續錯誤、等待時間、積壓或資料異常超過保護範圍。中止後仍要保存當下結果,完成必要復原與資料驗證,再開始下一次測試。
非同步流程要分開量測入口接受時間與端到端完成時間。入口快速接受只能說明工作已排入流程,還要確認消費速率、最舊工作等待時間及負載下降後的追趕時間。
遺留系統與目標系統要使用相同案例識別碼、操作比例、資料特徵、負載模型、測試階段與統計方式。環境無法完全相同時,應該記錄差異及其可能影響,避免直接比較兩個缺少共同基準的數字。
| 比較紀錄 | 應保存的內容 |
|---|---|
| 系統版本 | 原始碼版本、建置成品及容量相關設定 |
| 測試規格 | 案例識別碼、腳本版本、工具版本、資料版本與負載設定 |
| 環境條件 | 執行單位、容量限制、相依項目及測試期間的其他工作 |
| 對外結果 | 回應時間百分位、吞吐量、錯誤比例與功能結果 |
| 內部狀態 | 排隊、處理階段、相依等待、執行資源與積壓變化 |
| 容量結論 | 最大穩定負載、安全容量、第一個瓶頸及恢復時間 |
同一條件應該重複執行並記錄結果分布,不能只保留最好的一次。變異過大時要先找出環境、資料或背景工作的差異,再判斷版本之間的改善幅度。
目標系統不需要在每一項數字上超過遺留系統,但必須符合已核准的目標需求。任何為了效能而調整的程式、查詢、平行處理或快取,都要在相同情境下重新測試,並再次執行功能驗證,確認輸出與狀態變化沒有改變。
效能測試腳本、資料產生方式與設定應該納入版本控制。每次正式結果至少要保存下列資訊:
測試規模可以分層。小型代表情境適合在一般變更後快速執行,完整負載測試可以在準備發布時執行,壓力與耐久測試則按照成本及風險定期安排。自動化流程應該使用腳本中的驗收門檻決定通過或失敗,不能只產生一份沒有人判讀的圖表。
測試結果具有環境與版本範圍。系統程式、資料規模、部署設定、相依版本或工作負載模型明顯改變時,都要重新執行相關情境,不能長期沿用過期容量。