Performance Testing 入門 — k6 vs JMeter vs Locust 該選哪個
給 QA 看的效能測試完整入門。Load / Stress / Spike / Soak 四種類型差異、k6 實戰範例、跟 JMeter / Locust / Artillery 對比、CI 整合策略。
💡 本文原刊於 qa.9niche.com,2026-08 併入 9niche.com 懶人包,內容照原文完整搬遷。
目錄
1. 前言
「網站要扛得住 5000 人同時上線」是業務常常開的單。Performance test 不是壓爆它,是知道它什麼時候會爆。這篇給你 QA 角度的完整入門。
2. 4 種效能測試一次看懂
| 類型 | 模擬什麼 | 抓什麼 bug |
|---|---|---|
| Load | 正常流量 + 些許 buffer | 平均回應時間、throughput |
| Stress | 超量 2-5 倍 | 崩潰點、graceful degradation |
| Spike | 突發爆量 | autoscaling、queue 機制 |
| Soak | 正常量 8 小時+ | memory leak、connection leak |
多數團隊只做 Load,這是 80% 痛點來源。
3. 為什麼選 k6
| 工具 | 語言 | 學習曲線 | CI 友善 | 1 機可模擬人數 |
|---|---|---|---|---|
| k6 | JS | 低 | ⭐⭐⭐ | 30K+ VU |
| Locust | Python | 低 | ⭐⭐ | 5K VU |
| JMeter | XML / GUI | 中 | ⭐ | 10K VU |
| Gatling | Scala | 高 | ⭐⭐ | 50K+ VU |
| Artillery | YAML | 低 | ⭐⭐ | 5K VU |
新團隊建議 k6:JS 寫、CI 一行裝、效能最好。
4. 30 分鐘從 0 到 1:k6 第一個 test
1. 安裝(macOS)
brew install k6
或 Docker:
docker pull grafana/k6
2. 寫第一支腳本
// test.js
import http from 'k6/http';
import { check, sleep } from 'k6';
export const options = {
vus: 50, // 50 個 virtual users
duration: '30s', // 跑 30 秒
};
export default function () {
const res = http.get('https://staging.example.com/api/products');
check(res, {
'status is 200': r => r.status === 200,
'response time < 500ms': r => r.timings.duration < 500,
'has data': r => JSON.parse(r.body).length > 0,
});
sleep(1);
}
3. 跑
k6 run test.js
輸出長這樣:
✓ status is 200
✓ response time < 500ms
✓ has data
checks.........................: 100.00%
http_req_duration..............: avg=187.3ms p(95)=423ms p(99)=789ms
http_reqs......................: 1487 49.5/s
vus............................: 50
data_received..................: 2.3 MB
關鍵指標:
p(95) = 423ms— 95% 的 request 在 423ms 內回完p(99) = 789ms— 99% 在 789ms 內49.5/s— 每秒處理 49.5 個 request
5. 寫好 k6 腳本的 5 個原則
1. Stages — 階梯式加壓
export const options = {
stages: [
{ duration: '2m', target: 100 }, // 2 分鐘漸增到 100 VU
{ duration: '5m', target: 100 }, // 維持 5 分鐘
{ duration: '2m', target: 200 }, // 再增到 200
{ duration: '5m', target: 200 },
{ duration: '2m', target: 0 }, // 漸減回 0
],
};
突然開 1000 個 user 是 stress test 的玩法,load test 要漸進。
2. Thresholds — 自動 fail
export const options = {
vus: 50,
duration: '5m',
thresholds: {
http_req_duration: ['p(95)<500'], // p95 必須 < 500ms
http_req_failed: ['rate<0.01'], // 錯誤率 < 1%
'checks{group:checkout}': ['rate>0.95'],
},
};
CI 不過自動退 PR。
3. Scenarios — 真實場景
export const options = {
scenarios: {
browse_users: {
executor: 'ramping-vus',
stages: [{ duration: '5m', target: 80 }],
exec: 'browse',
},
checkout_users: {
executor: 'constant-vus',
vus: 20,
duration: '5m',
exec: 'checkout',
},
},
};
export function browse() { /* 瀏覽 */ }
export function checkout() { /* 結帳 */ }
80% 在瀏覽、20% 在結帳,比所有人都做同件事真實。
4. Setup / Teardown
export function setup() {
// 跑測試前:建測試帳號、塞測試資料
const res = http.post('/api/test-users');
return { token: res.json().token };
}
export default function (data) {
http.get('/api/profile', {
headers: { Authorization: `Bearer ${data.token}` },
});
}
export function teardown(data) {
// 清理
http.del(`/api/test-users/${data.userId}`);
}
5. Custom Metrics
import { Trend } from 'k6/metrics';
const checkoutTime = new Trend('checkout_time');
export default function () {
const start = Date.now();
// 跑 checkout 流程
checkoutTime.add(Date.now() - start);
}
業務指標自定義,不只看 HTTP timing。
6. 完整實戰範例:模擬電商高峰
import http from 'k6/http';
import { check, group, sleep } from 'k6';
export const options = {
scenarios: {
normal_browsing: {
executor: 'ramping-vus',
startVUs: 0,
stages: [
{ duration: '2m', target: 200 },
{ duration: '5m', target: 200 },
{ duration: '2m', target: 0 },
],
exec: 'browse',
},
checkout_flow: {
executor: 'constant-vus',
vus: 50,
duration: '7m',
exec: 'checkout',
},
},
thresholds: {
'http_req_duration{name:product_list}': ['p(95)<300'],
'http_req_duration{name:add_to_cart}': ['p(95)<500'],
'http_req_duration{name:checkout}': ['p(95)<1000'],
'http_req_failed': ['rate<0.01'],
},
};
const BASE_URL = __ENV.BASE_URL || 'https://staging.example.com';
export function browse() {
group('Browse', () => {
http.get(`${BASE_URL}/api/products`, { tags: { name: 'product_list' } });
sleep(2);
http.get(`${BASE_URL}/api/products/123`, { tags: { name: 'product_detail' } });
sleep(3);
});
}
export function checkout() {
group('Checkout', () => {
const r1 = http.post(`${BASE_URL}/api/cart`,
JSON.stringify({ sku: '123', qty: 1 }),
{ tags: { name: 'add_to_cart' }, headers: { 'Content-Type': 'application/json' } }
);
check(r1, { 'cart created': r => r.status === 201 });
sleep(1);
const r2 = http.post(`${BASE_URL}/api/orders`,
JSON.stringify({ cart_id: r1.json().id }),
{ tags: { name: 'checkout' }, headers: { 'Content-Type': 'application/json' } }
);
check(r2, { 'order placed': r => r.status === 201 });
sleep(2);
});
}
跑:
BASE_URL=https://staging.example.com k6 run --out json=results.json scripts/ecommerce.js
7. CI 整合(GitHub Actions)
name: Performance Test
on:
schedule:
- cron: '0 2 * * *' # 每天凌晨 2 點跑
workflow_dispatch:
jobs:
perf:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: grafana/[email protected]
with:
filename: perf/ecommerce.js
env:
BASE_URL: ${{ secrets.STAGING_URL }}
- if: failure()
uses: actions/upload-artifact@v4
with:
name: perf-results
path: results.json
不要每個 PR 都跑 — 太慢、太貴。跑 nightly 或 weekly 即可。
8. 結果該怎麼讀(指標解讀)
我看效能報告的順序
- Error rate — 有錯誤就先看這個
- p99 latency — 看最慘的 1%(這才是使用者罵的)
- p95 — 主要 SLA 指標
- Throughput trend — 看是不是穩定(崩盤前會先降速)
- Server-side metrics(搭配 Datadog / Grafana)— CPU / RAM / DB query
只看 average 是新手。Average 200ms 可能包含 p99 = 5 秒。
9. 反模式
- 本機跑大流量 — 1 機網路打不出 1000 RPS,要用雲端
- 沒 ramp-up — 突然 1000 VU 是 stress test 不是 load
- 打 prod — 除非你想被 fire
- 不清理 test data — 一個月後 staging DB 變垃圾場
- 沒設 threshold — 結果出來大家看一下、沒人 own
- 效能規格未談 — 沒 SLA 不知道過或不過
- 只跑一次 — 應該 nightly 跑、看趨勢
10. 跟其他工具的比較
k6 vs JMeter
- JMeter 強在 GUI 設計複雜流程、適合非工程師
- k6 強在 code 易維護、CI 整合、效能好
- 新案首選 k6
k6 vs Locust
- Locust Python 寫、容易上手
- k6 JS 寫、效能強 5-10 倍
- 重視效能選 k6、重視團隊 Python 熟悉度選 Locust
k6 vs Gatling
- Gatling Scala 寫、效能最強
- k6 JS 寫、夠用且容易
- 電商 / 金融大規模選 Gatling、中小團隊 k6 即可
11. 進階主題(之後可以深入)
- Distributed k6 — 雲端跑、模擬全球流量
- Browser-based perf — k6/browser 加 Chromium 跑(真實前端 perf)
- gRPC / WebSocket 測試 — k6 原生支援
- 整合 APM — Datadog / New Relic 看 server-side
- Continuous performance testing — 整合 SLO 監控
12. 給 QA 的關鍵 takeaway
效能測試不是「測一次過了就算」。它是:
- 建立 baseline(系統正常時的 p95)
- 每次大改動跑、看有沒有 regression
- 收集 trend、跟 PM 約 SLO
- 上線後配合 APM 監控
從一支 k6 腳本開始,3 個月後你會發現自己變不可或缺。
相關連結
從零搭起 API 測試框架。pytest fixtures、requests session、JSON schema 驗證、auth 處理、CI 整合,附完整範例。
給「會寫 test 但不懂 CI/CD」的 QA 看的入門。Pipeline 七階段、QA 在每一階段做什麼、quality gate 怎麼設、常見坑。
Cross-browser 測試完整策略。Browser matrix 怎麼決定、Playwright 跨瀏覽器、BrowserStack / Sauce Labs 比較、何時用真機、何時用 emulator、CI 整合。
相關懶人包
2026 QA 趨勢實戰:我看到的 5 個轉變(AI、Shift-Left、Observability)
從手動 QA 到 AI 輔助、從測試金字塔到測試獎盃。這篇分享我這 10+ 年看 QA 從「測完才知道」到「shift-left + AI」的真實觀察。
2026 QA 面試的 AI 題 — 12 題 + 答題框架(面試官想聽什麼)
2026 QA 面試新增一整類「你怎麼用 AI」的問題。這篇整理 12 個高頻 AI 面試題、每題附面試官真正想聽的點與答題框架,從「你用過哪些 AI 工具」到「AI 生的 test 怎麼信任」。
AI / LLM 功能 Spec Review — 幻覺 / 評估 / 成本 / 法遵 8 個必問
AI 功能 spec review 完整指南。LLM 不確定性處理、評估指標、Prompt versioning、成本控制、安全護欄、法遵(EU AI Act / GDPR)、Fallback、人工 review 流程。
一般聲明
本站提供之資訊僅供參考,不保證其完整性與正確性。使用者應自行判斷資訊之適用性。