一、同一個修改,兩種工具的一天
先講一個每個效能測試者都會遇到的日常:主管看完你的測試結果說「不錯,人數改成 50 再跑一次」。就這麼一句話,在不同工具裡是完全不同的體驗。
用 GUI 工具,你要開啟程式、載入專案、在左側的元件樹裡找到「執行緒群組」、點進欄位把 10 改成 50、存檔、重新執行。動作不難,但每一步都要人在畫面前操作。而下週主管問「這次跟上次的設定差在哪」,你得把兩個專案檔都打開來,一個欄位一個欄位對照——因為專案檔存的是一大包 XML,人眼很難直接比對。
用 k6,你昨天已經做過這件事了:連腳本都不用改,指令加個參數就重跑。
k6 run --vus 50 --duration 30s first-test.js
設定差在哪?指令列的歷史紀錄就是答案;如果改的是腳本,兩個純文字檔並排一看就知道。這個日常小場景,就是「GUI 工具」與「程式碼工具」最本質的分岔。

圖 1:同一個修改需求,兩種工作流——差別集中在「改動能不能被看懂、能不能被 AI 處理」
二、三個世代的工具:LoadRunner、JMeter、k6
這三個名字你在職缺描述和技術文章裡都會反覆看到,它們分別代表三個時代對效能測試的想像。

圖 2:三個世代的工具時間軸——最新的變化發生在協作對象:多了 AI
LoadRunner 誕生於 1990 年代,是商業授權的企業級老牌,協定支援極廣(不只 HTTP,連老式金融、ERP 協定都吃),大型企業與金融業至今仍大量使用。代價是授權費用高,腳本使用自家的 VuGen 環境,學習資源多半綁著企業訓練。
JMeter 是 Apache 基金會的開源專案,1998 年問世,用 GUI 點選的方式組裝測試,外掛生態累積了二十多年,中文資源豐富,是許多 QA 對效能測試的第一印象。它完全免費,也支援指令列模式跑進自動化流程。取捨在於:測試計畫存成 .jmx 的 XML 專案檔,版本比對困難;以 Java 執行緒模擬使用者,大量 VU 時對記憶體的需求可觀。
k6 於 2017 年開源,2021 年加入 Grafana 家族。它反過來想這件事:測試就是一段程式碼,用 JavaScript 描述行為,用 Go 語言的引擎執行(同樣的機器能模擬更多 VU),從第一天就為指令列與自動化而設計。沒有 GUI 可以點,這在過去被視為門檻——接下來你會看到,這件事的意義已經完全改變。
正式比較:同一把尺量三個工具
公平地說:這三個工具都能把效能測試做好,JMeter 的外掛生態與 LoadRunner 的協定廣度,k6 至今沒有完全取代。本系列選 k6 的理由很聚焦:對不會寫程式、要靠 AI 協作入場的測試人員,k6 的路最短。原因就在下一節。
三、關鍵差異:純文字腳本是 AI 的母語
「沒有 GUI、要寫程式」曾經是 k6 對 QA 最不友善的一點。AI 協作工具出現後,這一點整個翻轉了:AI 最擅長讀寫的就是程式碼,最難幫上忙的就是「請幫我在畫面上點這裡、點那裡」。工具沒變,變的是協作對象。
先看你已經認識的 k6 腳本,設定 10 個使用者長這樣:
export const options = {
vus: 10, // 10 個虛擬使用者
duration: '30s', // 跑 30 秒
};
同一件事,JMeter 的 .jmx 專案檔裡是這樣(節錄真實格式的其中一小段):
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup"
testname="Thread Group" enabled="true">
<stringProp name="ThreadGroup.num_threads">10</stringProp>
<stringProp name="ThreadGroup.ramp_time">1</stringProp>
<elementProp name="ThreadGroup.main_controller"
elementType="LoopController">
<boolProp name="LoopController.continue_forever">false</boolProp>
<intProp name="LoopController.loops">-1</intProp>
</elementProp>
<!-- 這只是節錄,完整檔案通常有數百行 -->
</ThreadGroup>
要誠實說:AI 也讀得懂 XML,請它修改 jmx 通常也改得出來。真正的差別在下一步——你能不能驗證它改對了。上面那段 k6 設定,你昨天才剛學,一眼就能確認 AI 是否照你的意思改;那段 XML,多數人只能「看起來應該沒問題」就送出去跑。AI 產出的速度越快,人的驗證能力就越是整條流程的瓶頸——選一個你驗證得動的格式,等於把這個瓶頸拆掉一半。這就是本系列選 k6 最核心的理由。

圖 3:AI 協作迴圈——需求、腳本、指令、輸出全是純文字,每一步你都插得上手
四、動手做:三個小實驗,親手驗證今天的說法
以下實驗全部沿用 Day 1 的環境與 first-test.js 腳本(文末附錄有完整腳本,跳過 Day 1 的讀者可直接取用)。練習目標仍是官方練習站 QuickPizza,維持小流量。
實驗一:一行參數,三種負載——體驗程式碼工具的迭代速度
把測試時間縮短成 10 秒,連續跑三種人數。三個指令,總共不到一分鐘:
k6 run --vus 1 --duration 10s first-test.js
k6 run --vus 5 --duration 10s first-test.js
k6 run --vus 10 --duration 10s first-test.js
每跑完一次,把三個關鍵數字抄進下表(沿用 Day 1 學過的判讀):
觀察重點有兩個。第一,總請求數大致隨 VU 等比增加,回應時間則幾乎持平——複習 Day 1 的結論:目前的量還遠在練習站的舒適區。第二,也是今天的重點:你剛剛在一分鐘內完成了三輪「修改設定、執行、記錄」的實驗迭代。回想第一節那個 GUI 工作流,同樣三輪要花多少動作?迭代速度就是程式碼工具的第一個紅利。
實驗二:讓 AI 讀兩種腳本——親自體驗「驗證得動」的差別
這個實驗不需要安裝任何東西,用你手邊任何一個 AI 聊天工具的網頁版就能做(之後系列會正式安裝 Claude Code,今天先用網頁版體驗)。做法:把本文第三節的兩段程式碼分別貼給 AI,各下一個修改任務,然後觀察你自己驗證答案的難易度。
Prompt A|請 AI 修改 k6 腳本
我是不會寫程式的測試人員。以下是一段 k6 的測試設定,
請把虛擬使用者改成 30 個、時間改成 60 秒,
並告訴我你改了哪幾個地方:
(貼上第三節的 k6 options 片段)
Prompt B|請 AI 修改 JMeter 專案檔片段
以下是 JMeter .jmx 檔案的片段。
請把執行緒數改成 30,並告訴我你改了哪裡:
(貼上第三節的 XML 片段)
兩個任務 AI 大概都能完成。關鍵問題是問你自己的:哪一個答案,你有把握判斷它改得對不對?k6 那段你能逐字確認;XML 那段你多半只能相信它。把這個感覺記下來——之後每次讓 AI 產生任何東西,「我驗證得動嗎」都是你要先問的問題,這一題比工具選型影響更深遠。
實驗三:改動看得見——純文字的版本比對紅利
複製一份腳本,改一個數字,然後讓差異自己現形:
# 複製一份腳本(macOS / Linux;Windows 可直接複製貼上檔案)
cp first-test.js first-test-v2.js
# 用編輯器把 first-test-v2.js 裡的 vus: 1 改成 vus: 5,存檔
# 比對兩個檔案的差異(Windows 用 fc 指令)
diff first-test.js first-test-v2.js
fc first-test.js first-test-v2.js
輸出只會列出改動的那一行。這就是純文字格式的日常紅利:任何改動都能被精確指認。給 RD 的延伸:這也代表 k6 腳本可以直接進 Git、走 code review、跟著產品版本一起演進——測試腳本從「某台電腦裡的專案檔」變成團隊共同資產。
五、注意事項:工具選型與導入,別踩這些坑
認識了三個工具的差異,接著是把「選工具」這件事放進真實職場時要注意的事。這一段 QA 與 RD 一起看,因為選型從來都是團隊決定:

給 QA 的一句話:如果你的公司已經用 JMeter 用得好好的,這個系列學到的觀念——負載、判讀、禮儀、與 AI 協作的方法——全部帶得過去,工具只是載體,不需要為了跟上系列而在公司裡發起換工具之戰。
六、觀念驗證:三個問題確認你有帶走今天的重點
• 主管問「為什麼新專案想用 k6,不用團隊熟的 JMeter?」——你能給出一個跟 AI 協作有關、而且講得出所以然的理由嗎?(第三節)
• 團隊有五百個運作中的 jmx 腳本,你會建議全部改寫成 k6 嗎?為什麼?(第五節)
• AI 幫你改了一段設定,k6 的版本和 jmx 的版本你都拿到了——哪一份你敢直接拿去跑?這個判斷標準叫什麼?(第三節、實驗二)
七、小結
今天認識了三個世代的工具,也親手驗證了「腳本即程式碼」的三個紅利:迭代快、AI 讀寫得了、改動比對得出來。更重要的是實驗二留下的那個問題——AI 產出的東西,我驗證得動嗎?這個問題會跟著你走完整個系列,它是效能測試的問題,也是 AI 時代每一種測試工作的問題。
附錄一:本篇指令速查
# 用參數覆寫人數與時間,快速迭代
k6 run --vus 1 --duration 10s first-test.js
k6 run --vus 5 --duration 10s first-test.js
k6 run --vus 10 --duration 10s first-test.js
# 比對兩個腳本的差異
diff first-test.js first-test-v2.js # macOS / Linux
fc first-test.js first-test-v2.js # Windows
附錄二:first-test.js 完整腳本(供跳過 Day 1 的讀者取用)
import http from 'k6/http';
import { check, sleep } from 'k6';
// ── 測試設定 ──────────────────────────────
// vus:同時模擬的「虛擬使用者」人數
// duration:整個測試要持續跑多久
export const options = {
vus: 1, // 先當 1 個人
duration: '30s', // 跑 30 秒
};
// ── 每個虛擬使用者重複做的事 ──────────────
export default function () {
// 對練習站首頁發出 GET 請求(等同瀏覽器打開網頁)
const res = http.get('https://quickpizza.grafana.com/');
// 檢查:伺服器回應的狀態碼是否為 200(代表成功)
check(res, {
'狀態碼是 200': (r) => r.status === 200,
});
// 停 1 秒再做下一輪,模擬真人操作的間隔
sleep(1);
}
iThome鐵人賽