一、你手上早就有素材
多數測試人員對「寫 k6 腳本」的想像是從空白檔案開始,其實幾乎不會。你手上早就有描述 API 的素材:Postman 裡累積的 collection、同事給的 curl 指令、API 文件的範例——它們都完整記載著「怎麼呼叫這個 API」。今天的主題就一句話:把這些素材交給 Claude Code 轉換成 k6 腳本,而非從零重寫。

圖 1:三種素材、一條轉換路——轉出來的腳本,三層驗收一步不能省
二、路徑一:從瀏覽器複製 curl,一分鐘變腳本
先教最普遍的來源——每個 QA 的瀏覽器裡就有。以 QuickPizza 實作:
• 打開 QuickPizza,按 F12 開啟開發者工具,切到 Network 頁籤
• 按一下網頁上的「Pizza, Please!」,Network 清單會出現一筆 api/pizza 的請求
• 在那筆請求上按右鍵 → Copy → Copy as cURL——你就拿到了這個 API 的完整呼叫方式:網址、方法、headers、送出的資料,一字不漏
在貼給 Claude Code 之前,先做一個必要的清理動作:瀏覽器複製出來的 curl 會帶著你的 Cookie 與各種身分 headers——在公司系統上,那就是你的登入身分。貼給任何雲端 AI 之前,把 -H 'Cookie: ...' 之類的行刪掉(練習站沒登入所以無妨,但習慣要在安全的地方先養成)。清理後用這個 prompt:
Prompt 1|curl 轉 k6
以下是我從瀏覽器複製的 curl 指令(已移除 Cookie)。
請把它轉成 k6 腳本,存成 from-curl.js:
人數 3 個 VU、時長 30 秒、驗證狀態碼 200、間隔 1 秒,
加上繁體中文註解,並告訴我原 curl 的哪個部分對應到腳本的哪一段。
(貼上清理後的 curl 指令)
注意 prompt 的最後一個要求:請它列出「curl 與腳本的對應關係」。這讓你能逐項核對轉換有沒有漏——這就是三層驗收的「讀」,只是這次對照的對象從五要素變成原始請求。轉完照例 1 個 VU 試跑。
三、路徑二:Postman collection 整批轉
如果你的 API 知識累積在 Postman:把 collection 匯出成 JSON 檔(Collection 右鍵 → Export),放進 perf-testing 資料夾,然後:
Prompt 2|Postman collection 轉 k6
資料夾裡的 my-apis.postman_collection.json 是 Postman 匯出檔。
請先列出裡面有哪些請求,等我挑選後,
再把我指定的那一個轉成 k6 腳本(3 VU、30 秒、驗證狀態碼、間隔 1 秒)。
如果檔案裡有看起來像 token 或密碼的值,先提醒我,不要寫進腳本。
兩個設計說明。先列清單再挑選:collection 通常有幾十支請求,一次全轉會得到一堆沒驗收過的腳本——一次轉一支、驗一支才是可控的節奏。要求它攔截機密:Postman 匯出檔常夾帶環境變數的實際值,這道提醒是安全網,但別依賴它——匯出前自己先檢查一次才是正辦。另外誠實說明轉換的極限:Postman 的 pre-request script 與測試腳本不會自動變成 k6 的對應邏輯,遇到有這些的請求,把它的用途講給 Claude Code 聽,讓它在 k6 裡重新實作。
四、職場變化型四連發:不用寫程式,用 prompt 講需求
接下來四個變化型,是你回公司實戰時最快遇到的。先講清楚這一節的定位:你不需要自己寫這些程式。這個系列的前提就是「不會寫程式也能做效能測試」,四個變化型也一樣——你的工作是三件事:認得出症狀、用 prompt 講得出需求、看得懂 Claude Code 改了什麼。每個變化型都用「症狀、Prompt、認得出來的寫法、注意」四段式;附上的示意碼不是要你抄,是讓你驗收時知道該看到什麼。

圖 2:四個變化型的共同節奏——症狀交給你辨識,程式交給 Claude Code
變化型一:Basic Auth——最老牌的帳密驗證
症狀:API 文件寫著「使用 Basic Authentication」,或 curl 指令裡有 -u 帳號:密碼。
Prompt 4-1|加上 Basic Auth
這支 API 使用 Basic Authentication(curl 裡是 -u 帳號:密碼)。
請修改 from-curl.js,讓每個請求帶上 Basic Auth,
帳號密碼不要寫死在腳本,改從環境變數 API_USER 與 API_PASS 讀取,
並告訴我執行時的完整指令。
認得出來的寫法:Claude Code 通常會給你以下兩種之一。你只要確認「帳密是從 __ENV 來的,不是寫死的字串」就算驗收通過。
// 寫法一:帳密放進網址(k6 會自動轉成 Authorization header)
const res = http.get(`https://${__ENV.API_USER}:${__ENV.API_PASS}@test.example.com/api/data`);
// 寫法二:自己組 Authorization header(base64 編碼)
import encoding from 'k6/encoding';
const credentials = encoding.b64encode(`${__ENV.API_USER}:${__ENV.API_PASS}`);
const res2 = http.get('https://test.example.com/api/data', {
headers: { Authorization: `Basic ${credentials}` },
});
注意:帳密從哪來?絕不是寫死在腳本——第五節的環境變數就是答案,這裡先在 prompt 裡把要求講出去。
變化型二:檔案上傳——報表、圖片、附件
症狀:要測的功能是上傳(大頭貼、Excel 匯入、附件)。
Prompt 4-2|檔案上傳測試
請寫一支 k6 腳本 upload-test.js:
把資料夾裡的 test-upload.jpg 用 multipart form 上傳到 https://test.example.com/api/upload,
表單另外帶一個欄位 description,值是「效能測試上傳」。
先用 1 個 VU 跑 10 秒,驗證狀態碼 200。
另外請幫我算:如果改成 20 個 VU、每秒各上傳一次,需要多少上行頻寬?
認得出來的寫法:看到 open() 在腳本最外層讀檔、http.file() 把檔案包成表單欄位,就是對的。
// open() 只能在腳本最外層讀檔(k6 的規定),測試中重複使用
const binFile = open('./test-upload.jpg', 'b'); // 'b' 代表二進位
export default function () {
const data = {
file: http.file(binFile, 'test-upload.jpg', 'image/jpeg'),
description: '效能測試上傳', // 表單的其他欄位照常放
};
const res = http.post('https://test.example.com/api/upload', data);
}
注意:上傳測試最先倒下的常是施壓端——20 個 VU 各自上傳 5MB 檔案,你自己的網路頻寬先滿。所以 prompt 最後一行順便請它算頻寬:檔案用小的、頻寬先估算,這在第六節注意事項還會提。
變化型三:URL 帶參數——別讓統計被切碎
症狀:測試會打 /api/users/1、/api/users/2……每個使用者一個網址。不處理的話,k6 會把每個網址當成不同端點各自統計:

圖 3:同一支 API 因為 ID 不同被切成上百條統計,每條只有零星樣本——p(95) 全部失真;分組後才是同一群
Prompt 4-3|合併 URL 統計
我的腳本會打 /api/users/1 到 /api/users/500,
k6 輸出裡出現了幾百條不同網址的統計,p(95) 沒有參考價值。
請修改腳本,讓所有 /api/users/{id} 的請求在統計上合併成同一個名稱,
並在輸出裡只看到一條 GET /api/users/{id}。
認得出來的寫法:兩種都對,重點是跑完後輸出裡只剩一條。
// 寫法一:http.url 模板——k6 自動以模板為名合併統計
const res = http.get(http.url`https://test.example.com/api/users/${userId}`);
// 寫法二:tags 指定統計名稱——效果相同,寫法更明白
const res2 = http.get(`https://test.example.com/api/users/${userId}`, {
tags: { name: 'GET /api/users/{id}' },
});
注意:Day 5 說過「樣本太少的百分位不可信」——這個變化型就是那條注意事項在腳本層的具體實踐。同一支 API 的請求,統計上就該是同一群。
變化型四:測試環境的自簽憑證——x509 錯誤
症狀:對公司測試環境跑第一次就噴錯,訊息裡有 x509 或 certificate 字樣——因為測試環境用的是自簽憑證,k6 預設拒絕不受信任的連線。這一型甚至不用改腳本,直接把錯誤訊息貼給 Claude Code:
Prompt 4-4|處理自簽憑證錯誤
我對公司測試環境跑 k6 出現以下錯誤(貼上含 x509 的錯誤訊息)。
這是內部測試環境的自簽憑證。請告訴我最不侵入腳本的處理方式,
並說明這個設定為什麼不能用在正式環境。
認得出來的寫法:
# 做法一:執行時加參數(推薦,腳本保持乾淨)
k6 run --insecure-skip-tls-verify my-test.js
// 做法二:寫進腳本 options
export const options = {
insecureSkipTLSVerify: true,
};
注意——必須講清楚的界線:這個設定的意思是「不驗證對方憑證」,只准用在你自己團隊的測試環境。正式環境的憑證錯誤是要修的問題,不是要跳過的問題。優先用指令參數,避免設定跟著腳本被帶去正式環境。
四個變化型走完,你會發現共同模式:prompt 裡講的都是症狀與約束(用哪種驗證、上傳什麼、統計要合併、環境是自簽憑證),沒有一行是在描述程式怎麼寫。這就是這個系列想建立的能力——把場景翻譯成需求,而不是把需求翻譯成程式。
五、環境變數:機密移出腳本的具體做法
Day 2 與 Day 4 都講過原則:機密永遠不寫死在腳本。今天補上做法——環境變數。腳本裡只記「要用一個叫 TOKEN 的值」,真正的值在執行的那一刻才從終端機給:

圖 4:機密與腳本分離——腳本進版控、貼給 AI 都安全,值只存在於執行的當下
動手改造自己的腳本。QuickPizza 的示範 token 雖是公開的,正好拿來安全地練習這個機制:
Prompt 3|把 token 改成環境變數
請修改 pizza-api-test.js:把 Authorization 裡的 token 值
改成從環境變數 API_TOKEN 讀取(用 __ENV.API_TOKEN),
並在腳本開頭加一段檢查:如果沒有提供 API_TOKEN 就報錯提醒。
改完告訴我新的執行指令長什麼樣。
改完後的關鍵段落與執行方式:
// 腳本裡:只有名字,沒有值
const HEADERS = {
'Content-Type': 'application/json',
'Authorization': `Token ${__ENV.API_TOKEN}`,
};
# 執行時才給值(練習用的是公開示範 token)
k6 run -e API_TOKEN=abcdef0123456789 pizza-api-test.js
從此這支腳本可以放進版控、貼給 AI、分享給同事——裡面沒有任何秘密。在公司環境,真正的 token 就用同一套方式傳入;接上自動化流程時,值改由平台的秘密管理機制提供,機制完全相同。
六、注意事項:轉換與變化型的坑

給 RD 的一句話:QA 同事從 DevTools 抓 curl 來轉腳本的時候,最需要你幫的一件事是:告訴他們哪些 headers 是身分、哪些是必要的業務參數——一張「這個系統的 headers 清單」,能同時提升他們的腳本品質和全隊的資安水位。
七、觀念驗證:三個問題確認你有帶走今天的重點
• 同事把從公司系統複製的 curl 原封不動貼進雲端 AI 問問題——風險是什麼?他該先做哪個動作?(第二節、第六節)
• 測試打了 /api/orders/10001 到 /api/orders/10500,輸出裡有五百條統計——這對 p(95) 的可信度造成什麼影響?你會怎麼跟 Claude Code 描述這個需求?(第四節變化型三)
• 為什麼「執行時 -e 給值」比「把 token 寫進腳本再小心不要外流」更安全?從版控歷史的角度想一想。(第五節)
八、小結
今天的主軸是「轉換而非重寫」:DevTools 的 Copy as cURL 和 Postman 匯出,是你早就擁有的 API 知識存摺,Claude Code 負責把它們兌換成 k6 腳本,你負責對照原始請求逐項驗收。四個變化型(Basic Auth、檔案上傳、URL 分組、自簽憑證)全部靠 prompt 描述症狀與約束來解決——你要練的不是寫法,是認得出場景、開得出需求;環境變數則把「機密不進腳本」從原則變成了每天的做法。特別記住那個一秒鐘的動作:貼 curl 給 AI 之前,先刪 Cookie。
附錄:curl 與 k6 對應速查

# 環境變數用法速查
k6 run -e API_TOKEN=xxx -e BASE_URL=https://staging.example.com my-test.js
// 腳本內讀取
const token = __ENV.API_TOKEN;
const base = __ENV.BASE_URL || 'https://quickpizza.grafana.com'; // 可設預設值