Claude Codeでk6負荷テストのスクリプトを作成する手順
k6負荷テストのJavaScriptスクリプトをClaude Codeに書かせる手順です。VU数と実行時間の指定、しきい値、GitHub Actionsへの組み込みまで扱います。
Claude Codeにk6のシナリオを書かせると、雛形生成からしきい値設計、CI組み込みまでの反復作業を短くできます。対象エンドポイントとVU数(仮想ユーザー数)を伝えるだけで、k6のJavaScript構文に沿ったスクリプトが返ってきます。k6のスクリプトはimport http from 'k6/http'で始まり、optionsでVU数と実行時間を決め、export default functionにリクエストを書くのが基本形です。実際のコードは手順1にあります。以降で、基本シナリオの生成からGitHub Actionsへの組み込みまでを順に扱います。
Claude Codeでk6スクリプトを書かせるとはどんな作業か
k6はGrafana Labsが開発するオープンソースの負荷テストツールで、テストシナリオをJavaScriptで記述します。HTTPリクエストベースの負荷テストが中心ですが、k6 browser APIを使えばブラウザを操作するシナリオも同じ構文で書け、CI/CDへの組み込みや障害注入を使ったカオステストにも対応します。Claude Codeはk6専用の統合機能を持つわけではなく、他のテストコードを書かせる作業と同じ、通常のコーディング支援としてk6のスクリプトを生成します。
そのため精度を左右するのは、対象URL・リクエスト方式・想定VU数・実行時間といった条件をどれだけ具体的に伝えるかです。既存コードにテストを書かせる進め方全般はClaude Codeでテストを書かせる実践手順にまとめており、対象を絞って条件を先に固めるという考え方はk6のシナリオ生成でも同じです。
前提条件
k6のCLIをローカルまたはCI環境にインストールしておきます。Macではbrew install k6、Debian/Ubuntu系ではAPTリポジトリ経由のパッケージが公式に用意されています。
brew install k6Dockerイメージgrafana/k6も配布されているため、CLIを直接インストールしたくない場合はコンテナ経由でも実行できます。加えて、テスト対象は本番環境ではなくステージングや専用の負荷テスト環境を用意します。実際に負荷をかけるテストなので、対象システムの許可なく本番URLに向けて実行しないよう注意します。
複数のパッケージでk6スクリプトを書く機会が繰り返しあるチームは、対象エンドポイントの命名規則やしきい値の既定値をSKILL.mdにまとめておくと、Claude Codeが毎回同じ規約でスクリプトを生成します。モノレポでテスト規約をSKILL.mdに教える手順はClaude Codeモノレポのテスト戦略をSKILL.mdで教える手順にまとめています。
手順1: 基本シナリオをClaude Codeに生成させる
最初に、対象エンドポイントと負荷条件を具体的に伝えて雛形を生成させます。
k6でJSのロードテストスクリプトを書いて。対象はhttps://staging.example.com/healthへのGETリクエスト、5 VUsで30秒間実行してこの指示から、Claude Codeは次のような雛形を生成します。
import http from 'k6/http';
import { sleep } from 'k6';
export const options = {
vus: 5,
duration: '30s',
};
export default function () {
http.get('https://staging.example.com/health');
sleep(1);
}k6のスクリプトは、決まった順序で4つの段階を通ります。
k6スクリプトの4つの実行段階
init(必須)
optionsの定義やimportを含む、スクリプトの冒頭部分です。VUごとに1回実行されます。setup(省略可)
テスト全体で1回だけ実行され、全VUで使うデータを用意します。
VUコード(必須)
export default functionの中身で、反復のたびに実行されます。VUは並列に動くwhile(true)ループに近いモデルです。teardown(省略可)
テストの最後に1回実行され、setupの結果の後処理に使います。
setup()が例外で終わると呼ばれません。
実際のAPIは単一エンドポイントだけで完結しないことが多く、ログインしてトークンを受け取り、そのトークンを使って認証済みリクエストを送るという流れを再現したい場面があります。「ログインAPIをPOSTで呼び、レスポンスのトークンをAuthorizationヘッダーに載せて/profileへGETして」のように依存関係まで含めて指示すると、Claude Codeは1回のVU実行の中で複数のhttpリクエストを順に呼び出し、各レスポンスを検証するスクリプトを生成します。
対象URLをスクリプトに直書きすると、ステージングと本番、PRごとのプレビュー環境で使い分けにくくなります。__ENV.TARGET_URLのように環境変数からURLを読み込む形にしておくと、k6 run -e TARGET_URL=https://staging.example.com/health script.jsのようにCLIから対象を切り替えられます。GitHub Actionsに組み込むときも、この仕組みのままワークフロー側のflagsから値を渡せます。
生成したスクリプトはk6 runコマンドで実行します。
k6 run script.js手順2: しきい値とステージで本番想定に近づける
固定VU数の一発実行だけでは、実運用に近い負荷パターンを再現できません。Claude Codeに「立ち上がりと収束を含めたステージ構成にして」と伝えると、stages配列を使ったランピング設計に書き換えてくれます。
import http from 'k6/http';
import { check, sleep } from 'k6';
export const options = {
stages: [
{ duration: '30s', target: 20 },
{ duration: '1m30s', target: 10 },
{ duration: '20s', target: 0 },
],
thresholds: {
http_req_failed: ['rate<0.01'],
http_req_duration: ['p(95)<200'],
},
};
export default function () {
const res = http.get('https://staging.example.com/health');
check(res, { 'status was 200': (r) => r.status === 200 });
sleep(1);
}thresholdsはテストの合否を決める条件です。上の例では、HTTPエラー率が1%未満かつ95パーセンタイルのレスポンス時間が200ms未満であることを求めています。
check()とthresholdsの役割分担
check()
失敗してもテストは止まらず、終了ステータスも失敗になりません。結果はchecks_total・checks_succeeded・checks_failedの3つのメトリクスに記録されます。
thresholds
メトリクスに合否の条件を付けます。条件を割るとk6の終了ステータスが失敗になるため、そのままCIの合否判定に使えます。
checkの成功率そのものをゲートにするには、checksメトリクスにしきい値を足します。公式の例はchecks: ['rate>0.9']で、成功率が90%を超えることを求める書き方です。
しきい値の集計方法はメトリクスの型によって変わります。
| メトリクス型 | 使える集計方法 |
|---|---|
| Counter | 使える集計方法count、rate |
| Gauge | 使える集計方法value |
| Rate | 使える集計方法rate |
| Trend | 使える集計方法avg、min、max、med、p(N)(パーセンタイル) |
どのくらいのVU数・実行時間を選ぶべきかは、テストの目的によって変わります。k6公式は6種類のテストタイプを挙げており、Claude Codeに条件を伝えるときの目安になります。
| タイプ | VU/スループット | 実行時間 | 使うタイミング |
|---|---|---|---|
| Smoke | VU/スループット低い | 実行時間数秒〜数分 | 使うタイミングコード変更のたびに、最低限の動作を確認する |
| Load | VU/スループット想定される通常運用相当 | 実行時間5〜60分 | 使うタイミング平常時の性能を確認する |
| Stress | VU/スループット想定を上回る高負荷 | 実行時間5〜60分 | 使うタイミング想定超えの負荷にどう耐えるかを確認する |
| Soak | VU/スループット平常運用相当 | 実行時間数時間 | 使うタイミング変更後に長時間稼働での劣化を確認する |
| Spike | VU/スループット非常に高い | 実行時間数分 | 使うタイミング突発的なトラフィック急増への耐性を確認する |
| Breakpoint | VU/スループット限界まで段階的に増加 | 実行時間必要な分だけ | 使うタイミングシステムの上限を探る |
いきなりStressやSoakから始めず、まずSmokeでスクリプト自体が正しく動くかを確認してから段階を上げるのが公式の推奨です。
リクエスト率を固定する(到着率ベースのシナリオ)
vusとdurationで書くシナリオは閉じたモデルです。この性質で測定結果が偏る現象を、公式はcoordinated omissionと呼んでいます。毎秒30リクエストのように頻度そのものを決めたいときは、constant-arrival-rateエグゼキューターを使います。
閉じたモデルと開いたモデル
閉じたモデル
前の反復が終わってから次が始まります。応答が遅いほど、テスト中に走る反復の数が減ります。
開いたモデル
応答時間に関係なく、決めた割合で反復を開始します。足りないVUはk6が追加で起動します。
import http from 'k6/http';
export const options = {
discardResponseBodies: true,
scenarios: {
health: {
executor: 'constant-arrival-rate',
duration: '30s',
rate: 30,
timeUnit: '1s',
preAllocatedVUs: 2,
maxVUs: 50,
},
},
};
export default function () {
http.get('https://staging.example.com/health');
}rateとtimeUnitで開始頻度を、preAllocatedVUsとmaxVUsで使うVU数の幅を決めます。maxVUsを省くとpreAllocatedVUsと同じ値になります。到着率系のエグゼキューターは反復の間隔を自分で調整するため、反復の末尾にsleep()を置く必要はありません。Claude Codeへの指示にも、「毎秒30リクエストを30秒間、arrival-rateで」のように単位まで書いておくと、VU数ベースのスクリプトに寄るのを避けられます。
手順3: GitHub Actionsに組み込む
k6を継続的に実行するには、CIパイプラインへの組み込みが定番です。以前はgrafana/k6-actionという単体のGitHub Actionが使われていましたが、このActionはアーカイブされ保守が止まっています。現在の公式手順は、k6のセットアップを担うsetup-k6-actionと実行を担うrun-k6-actionを組み合わせる方式です。
Claude Codeにワークフローの生成を依頼する場合は、対象スクリプトのパスとトリガー条件を伝えます。
scripts/load-test.jsをpush時に実行するGitHub Actionsワークフローを書いて。setup-k6-actionとrun-k6-actionを使って生成されるワークフローは次のような形になります。
name: Load test
on: [push]
jobs:
load-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: grafana/setup-k6-action@v1
- uses: grafana/run-k6-action@v1
with:
path: |
./scripts/load-test.jssetup-k6-actionはk6-versionでバージョンを固定でき、未指定なら最新版が入ります。
Grafana Cloud k6に結果を送りたい場合は、K6_CLOUD_TOKENとK6_CLOUD_PROJECT_IDをGitHub ActionsのSecretsに登録し、envとして渡します。トークンをワークフローファイルに直書きしないよう、必ずSecrets経由にします。k6 v2.0.0以降では、クラウド系のコマンドにスタック情報も必要です。K6_CLOUD_STACK_ID環境変数、CLIフラグ、スクリプトのoptions.cloud.stackIDのどれかで渡します。run-k6-actionはこの値を検証せず、不足していればk6自体がエラーを返します。
run-k6-actionにはdebugやfail-fastといった入力もあります。既定ではサマリーだけがログに出ますが、debug: trueにするとk6の実行ログがそのままGitHub Actionsのログに出力されます。parallel: trueで複数のスクリプトを並列実行でき、fail-fast: trueなら最初の失敗でパイプラインを失敗させます。fail-fastの既定値は、入力の一覧表ではfalse、サンプルのコメントではdefault: trueと書かれていて食い違っています。挙動を当てにするなら、値を明示します。
CI環境の作り込み自体をClaude Codeに任せる進め方はClaude Codeセルフホスト環境をCIでE2Eテストするでも扱っており、認証情報をSecrets経由で渡す考え方は今回のk6連携とも共通します。
よくあるつまずき
古いgrafana/k6-actionの例をそのままコピーしがちです。ブログ記事やStack Overflowの過去の回答には旧Action単体の例が多く残っています。新規にワークフローを組むときは、保守が続いているsetup-k6-actionとrun-k6-actionの組み合わせに寄せます。
VU数を上げても、リクエスト数は比例して増えません。頻度を決めたいときは、手順2の到着率ベースのシナリオを使います。
しきい値を「テストを止める条件」と誤解しがちです。デフォルトのしきい値は、テスト終了後に合否を判定するだけで、条件を満たさない時点で実行を中断するわけではありません。しきい値の設定でabortOnFailを指定した場合のみ、条件を割った時点でテストが打ち切られます。開始直後の少ないデータで落ちるのを避けたいときは、delayAbortEvalで判定を遅らせます。
thresholds: {
http_req_duration: [
{ threshold: 'p(95)<200', abortOnFail: true, delayAbortEval: '10s' },
],
},大規模な負荷テストを本番デプロイをブロックするパイプラインに組み込むと、リリースが滞ります。1回の実行に3〜15分以上かかることも珍しくなく、デプロイ直前のパイプラインに組み込むとリリース全体が長引きます。公式ガイドも、大規模テストは自動デプロイ用パイプラインの外、専用環境でのリリース前検証に回すことを勧めています。
しきい値のPass/Failをそのままリリースのゲートにするのも要注意です。テスト対象のスクリプトやSLO自体が誤っている可能性もあるため、しきい値の判定結果は「詳しい調査が必要なシグナル」として扱い、判定基準がこなれるまでは全面的なブロック条件にしないという考え方が公式に案内されています。
まとめ
Claude Codeへの指示は、対象URLとVU数・実行時間に加えて、固定したいのが同時ユーザー数かリクエスト率かを先に決めて伝えると、スクリプトのモデルがぶれません。
参照した一次ソース
この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。
- grafana.com/docs/k6/latest
- grafana.com/docs/k6/latest/get-started/running-k6
- grafana.com/docs/k6/latest/using-k6/thresholds
- grafana.com/docs/k6/latest/testing-guides/test-types
- grafana.com/docs/k6/latest/testing-guides/automated-performance-testing
- grafana.com/docs/k6/latest/set-up/install-k6
- grafana.com/docs/k6/latest/using-k6/test-lifecycle
- grafana.com/docs/k6/latest/using-k6/checks
- grafana.com/docs/k6/latest/using-k6/scenarios/executors/constant-arriv…
- grafana.com/docs/k6/latest/using-k6/scenarios/concepts/open-vs-closed
- github.com/grafana/setup-k6-action
- github.com/grafana/run-k6-action