iT邦幫忙

2026 iThome 鐵人賽

DAY 7
0
Software Development

不會寫程式,我照樣做效能測試 - Claude Code × k6 的 30 天系列 第 7

Day 7|Checks 與 Thresholds:第一次有意義的 Smoke Test

  • 分享至 

  • xImage
  •  

一、從「人工看數字」到「讓測試自己宣判」

Day 5 之後,你已經看得懂輸出了。但想像一個場景:這支測試以後每天都要跑,難道每天都要有人盯著輸出,逐項判斷「這樣算過嗎」?人工判讀無法規模化,而且標準會隨著判讀的人飄移——今天你覺得 300ms 可以,下週同事覺得不行。

解法是把判斷標準寫進腳本,讓測試跑完自己宣判過或不過。這就是 threshold(門檻)的角色。從此測試的產出從「一堆數字」升級為「一個結論+一堆佐證數字」——而訂標準這件事,正是測試人員的專業所在,工具只是忠實執行你訂的標準。

二、check 與 threshold:觀察員與裁判

這兩個機制長得像、常被混用,分工其實非常清楚:

https://ithelp.ithome.com.tw/upload/images/20260905/20161809PA2ppvPXIe.png
圖 1:check 批改每張考卷但不擋人,threshold 訂及格線並判定整場測試的生死

關鍵差異在後果:check 失敗只記錄、不中止,Day 4 的實驗你已經看過——checks 掉到 50%,測試照樣跑完。threshold 不達標則是整個測試判定失敗,k6 的結束代碼(exit code)會是非 0,之後任何自動化流程都能據此把關。

兩者還能串接:所有 check 的通過率本身就是一個指標(checks),threshold 可以拿它來訂及格線,例如「check 通過率必須高於 99%」。觀察員的紀錄,成了裁判的判決依據。

三、動手做:幫腳本加上門檻,然後故意讓它失敗

第一步:請 Claude Code 加上 thresholds

Prompt 1|為腳本加上判定標準

請幫 pizza-api-test.js 加上 thresholds,標準如下:
1. 錯誤率(http_req_failed)要低於 1%
2. 95% 的請求(http_req_duration 的 p95)要快於 800 毫秒
3. check 通過率要高於 99%
只修改 options 區塊,其他不要動,並解釋你加了什麼。

修改後的 options 區塊會像這樣(照例:確認它只動了該動的地方再允許):

export const options = {
  vus: 5,
  duration: '30s',
  thresholds: {
    // 整體門檻:任何一條不滿足,整個測試判定失敗
    http_req_failed: ['rate<0.01'],    // 錯誤率低於 1%
    http_req_duration: ['p(95)<800'],  // 95% 的請求快於 800ms
    checks: ['rate>0.99'],             // check 通過率高於 99%
  },
};

跑一次 k6 run pizza-api-test.js,輸出裡每個有門檻的指標旁會多出通過標記。對 QuickPizza 的小流量測試,這三條應該全數通過。

第二步:故意讓門檻失敗一次

和 Day 4 弄壞 check 一樣,門檻也要先看過它「會失敗」才算認識它。自己動手把 p(95) 的門檻改成一個不可能達到的值:

    http_req_duration: ['p(95)<50'],   // 從台灣到練習站,50ms 幾乎不可能

再跑一次,你會看到兩個新東西——指標旁的失敗標記,以及結尾的錯誤訊息(樣式隨版本略異):

  ✗ http_req_duration : avg=182ms min=155ms med=170ms max=890ms
        'p(95)<50' p(95)=261ms

ERRO[0031] thresholds on metrics 'http_req_duration' have been crossed

接著查看結束代碼——這是門檻機制真正的威力所在:

# Windows(PowerShell)
echo $LASTEXITCODE
 
# macOS / Linux
echo $?

門檻沒過時它是非 0(通常是 99),全數通過時是 0。機器看不懂報告,但看得懂結束代碼——這一個數字,就是之後把效能測試接進任何自動化流程的鑰匙。看完把門檻改回 800,重跑確認恢復通過。

四、門檻怎麼訂:量出來的,不是許願出來的

最常見的新手問題:「800ms 這個數字哪來的?」答案的原則只有一條:門檻要不是來自服務等級目標(SLO),就是來自實測基準——絕不是拍腦袋。沒有 SLO 可依的時候,用這五步從零建立:

https://ithelp.ithome.com.tw/upload/images/20260905/20161809ecETueQlFb.png
圖 2:門檻五步訂法——先量基準、取最差值、加緩衝、寫進腳本、定期檢視

• 同條件跑 3 次,記下每次的 p(95)——單次數字會漂移(Day 5 講過),3 次是最起碼的樣本
• 取 3 次中最差的那個當基準——用最差值訂門檻,避免好日子的數字讓門檻虛胖
• 基準乘上 1.3 到 1.5 的緩衝——留出正常波動的空間,門檻抓的是異常,不是波動
• 寫進腳本、跟著進版控——門檻是團隊的共同承諾,不是某個人腦中的默契
• 數據累積後定期檢視——系統變快就收緊,架構變了就重量基準

另外記住定位差異:smoke test 的門檻刻意寬鬆,它的任務是抓災難(服務掛了、慢到離譜),不是守精確的服務水準;嚴格的門檻屬於之後正式的負載測試。門檻訂太嚴,天天誤報就成了狼來了;訂太鬆,等於沒訂。

五、延伸:同一套本事,也能做 API 功能測試

這一段對 QA 特別划算。把 options 換成「一個人、只跑一輪」,check 多寫幾條,k6 就從效能測試工具變成輕量的 API 功能測試工具——官方文件把這種用法正式稱為 functional testing:

export const options = {
  vus: 1,          // 一個人
  iterations: 1,   // 只跑一輪——只問對不對,不問快不快
  thresholds: {
    checks: ['rate==1'],  // 功能測試:每一條驗證都必須通過
  },
};
 
export default function () {
  const res = http.post(/* ...同 Day 4 的請求... */);
 
  check(res, {
    '狀態碼是 200': (r) => r.status === 200,
    '回應是 JSON': (r) => r.headers['Content-Type'].includes('json'),
    '有回傳披薩名稱': (r) => r.json('pizza.name') !== undefined,
    '熱量欄位是數字': (r) => typeof r.json('pizza.calories') === 'number',
  });
}

誠實的定位:它不會取代你手上的 Postman 或自動化測試框架——沒有測試報告網頁、斷言寫法也陽春。但它的價值在同一套腳本、同一套技能,冒煙與效能兩用:白天當功能檢查跑一輪,要壓測時把 vus 和 duration 換回來就是效能測試。對剛把 k6 學起來的你,這是免費的第二個用途。

六、本週驗收:對你負責的 API,走一次完整流程

第一週的所有能力,今天串成一條線用在真實工作上。目標:對你工作上負責的一個 API 或頁面,完成一次專業的 smoke test。

https://ithelp.ithome.com.tw/upload/images/20260905/20161809pHMKb8tPre.png
圖 3:第一次職場 smoke test——五問、告知、生成、小流量、判讀、回報

• 五問檢查(Day 6):授權、環境、告知、時間、止血——任何一問卡住就先停
• 發出告知:用 Day 6 生成的範本填空,貼到團隊頻道
• 生成腳本:Day 4 的五要素 prompt,加上今天的 thresholds(smoke 定位,門檻寬鬆:例如錯誤率 < 1%、p(95) < 2 秒)
• 小流量執行:1 到 2 個 VU、30 到 60 秒——smoke 的重點是「活著嗎」,不是「撐多少」
• 判讀:Day 5 的速查清單——checks、錯誤率、med 與 p(95)
• 簡短回報:一句結論(門檻全過/哪條沒過),附上原始輸出讓結論可被驗證

公司環境暫時不方便的讀者,用 QuickPizza 把整套流程完整走一遍當彩排——包括寫一則(不真的發出的)告知訊息。流程走順了,換上公司的目標只是改一個網址。完成這個驗收,你就達成了第一週的承諾:在職場做出第一次有意義的效能測試。

七、注意事項:訂門檻與跑 smoke 的坑

https://ithelp.ithome.com.tw/upload/images/20260905/20161809xdK7wkE254.png

給 RD 的一句話:threshold 的結束代碼設計,和你熟悉的單元測試 exit code 是同一個語言——這意味著 QA 訂的效能門檻,可以用你們現有的自動化基礎設施把關,不需要另一套系統。當 QA 同事拿著門檻數字來討論時,那是在跟你談合約,值得認真對。

八、觀念驗證:三個問題確認你有帶走今天的重點

• 同事的腳本 checks 只有 85%,但測試顯示通過;另一支 checks 100% 卻判定失敗——分別可能發生了什麼事?(第二節)
• 主管問「p(95) < 800ms 這個門檻怎麼來的」——你的標準答案是哪兩種來源?如果都沒有,你會怎麼建立?(第四節)
• 為什麼 smoke test 的門檻要刻意寬鬆?把正式 SLO 門檻放進每天跑的 smoke,會發生什麼事?(第四節、第七節)

九、小結:第一週結束,盤點你身上的裝備

今天學會了讓測試自己宣判:check 當觀察員、threshold 當裁判、結束代碼是通往自動化的鑰匙;門檻用五步量出來,而且 smoke 與 load 各有各的標準;順手多拿了一個免費用途——輕量 API 功能測試。

第一週到此為止,盤點一下:你知道效能測試回答哪三個問題(Day 1)、為什麼選 k6 與怎麼跟 AI 分工(Day 2、3)、五要素生成與三層驗收(Day 4)、判讀輸出與百分位數(Day 5)、五問禮儀與止血(Day 6)、訂門檻與宣判(Day 7)。這一套已經足夠你在職場安全、專業地完成 smoke 級的效能測試——而且每一步都知道自己在做什麼。下一週,開始面對真實系統的麻煩。

附錄:thresholds 常用寫法速查

thresholds: {
  // 錯誤率低於 1%
  http_req_failed: ['rate<0.01'],
 
  // p95 低於 800ms(可同時訂多條)
  http_req_duration: ['p(95)<800', 'p(99)<1500'],
 
  // 平均與中位數也可以當門檻(較少用,理由見 Day 5)
  // http_req_duration: ['avg<500', 'med<300'],
 
  // check 通過率高於 99%;功能測試模式用 rate==1
  checks: ['rate>0.99'],
}

結束代碼查詢:Windows(PowerShell)用 echo $LASTEXITCODE;macOS/Linux 用 echo $?。0 代表門檻全數通過,非 0 代表有門檻未達標。


上一篇
Day 6|壓測禮儀:按下執行之前,先確認你不會害到別人
下一篇
Day 8|HTTP 請求實戰:把 Postman 和 curl 變成 k6 腳本
系列文
不會寫程式,我照樣做效能測試 - Claude Code × k6 的 30 天11
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言