TL;DR
- JMeterを触る前に「テスト戦略 → テストシナリオ → テストケース → テストスクリプト」の階層を分けて整理せよ。 これが混在した仕様書のままだと、何時間JMeterと格闘しても1%も進まない。
- 「同時接続100人」は要件であってシナリオではない。 「ログインしてこの画面を開いてこのボタンを押す」まで分解されて初めてJMeterに落ちる。
- 性能テストの環境は、テスト実施者が「独占」できる状態にする。 バッチや他人の操作が混ざった瞬間、計測値は無駄になる。
- 「テストデータが事前作成されている」は信じない、必ず中身を確認する。 設定ミス・データ不足・機能差分で「負荷ゼロのテスト」が爆誕する。
- JMeterの難易度は単体・結合テストの10倍。 工数見積もりも10倍と思っておく。
はじめに
弊チームではある在庫系業務システムの性能テストを担当することになった。短納期かつ前任者不在の状況。だが、JMeterの既存資産はある。テスト仕様書も支給されている。 ―― という条件で、自分はサーバーサイドのテックリードという立場から実施計画を引き取った。
結論から言うと、「短納期かつ前任者不在の状況で性能テスト結果を出す」というゴールはこの時点で破綻していた。 その理由と、初めて性能テストをやるエンジニアが踏むべきだった手順を、失敗ベースで残しておく。
やらかし1: JMeterの「使い方」から入ってしまった
着手初日、自分(と担当メンバー)は素直にJMeterのチュートリアルを読み始めた。スレッドグループ、HTTPリクエストサンプラー、リスナー、CSV Data Set Config... 一通り触ればなんとかなる気がしていた。
なんともならなかった。理由はシンプルで、「何をテストするか」が決まっていなかったからだ。
支給されたテスト仕様書を見直すと、以下が混在していた。
- テスト戦略(目的・適用範囲・成功条件)
- テストシナリオ(100ユーザー同時接続、Web業務 + ハンディ業務並走 など)
- テストケース
- テストステップ(ログインAPIを叩く、商品検索APIを叩く...)
この状態でJMeterのテストプランを設計しようとしても、「テストプラン1個 = テストシナリオ1個」の対応すら取れない。 スレッドグループを何個切ればいいかも分からない。
やらかし2: 「同時接続100人」をテストケースだと思っていた
仕様書には「ピーク同時接続100ユーザー」と書かれていた。自分は最初これをテストケースだと読んでいた。
違った。これはテスト戦略の中の「達成条件」であって、「100人が同時に何をするのか」が定義されていない時点でシナリオにすらなっていない。
レビュアーから入った指摘を要約するとこうだ。
「100人で同時接続」というのは要件。「100人がログインしてA検索画面でリロードを連打する」「100人が端末でA機能を使う」「A業務50人 + B業務50人」のどれかによって、必要なJMeterスクリプトもDB負荷も全然違う。まずシナリオの粒度まで分解してから来い。
つまり階層はこう。
テスト戦略(目的・適用範囲・KPI)
└ テストシナリオ(100人がA業務を実行する、など)
└ テストケース(ログイン後、A一覧を表示する、など)
└ テストステップ / スクリプト(実際に叩くAPI・パラメータ)
JMeterのテストプランは、この一番下の層を実装するためのツールだ。一番上から作らないと意味がない。
やらかし3: 「テスト対象API」がそもそも特定できていなかった
仕様書には「A業務」「B業務」と書かれていた。が、「業務」が指す画面・APIの区別がつかない。
例えば「入荷業務」と書かれていても、
- 入荷予定取り込み → 自動引当 → 検品 → 格納
- これらのうち、案件カスタマイズでA工程が追加されている
- 一部はバッチ、一部はAPIで動いている
という構造になっており、「どのAPIを何件叩けば負荷テストになるのか」を決めるにはドメイン知識が要る。これは「JMeterの使い方が分かれば解ける問題」ではなかった。
ここで自分は、「テスト対象API一覧」を完成させずにJMeterのHTTPサンプラーを書き始めようとしていた。ボツ。
もちろんAIを使ってコードリーディングをすれば出せるものもあるが、それは対象がわかっていないと意味がない。
やらかし4: テストデータを信用してしまった
仕様書には「テストデータは事前作成」と書かれていた。これも罠だった。
実際には、
- データ作成先が本番想定ではなくテスト想定で作られていた可能性
- 在庫データがゼロで、引当処理が即エラーになる可能性
- カスタマイズで追加されたテーブルにデータが入っていない可能性
があり、**「テストは流れたが、実際にはどの処理にも負荷がかかっていなかった」**という状況になっていた。
性能テストの正否は「数字が良い・悪い」ではなく、「想定通りの負荷が本当にかかっていたかを後から検証できるか」 で決まる。テストデータの中身を1件1件SQLで確認する工程は省略してはいけなかった。
やらかし5: 環境隔離を考えていなかった
「テスト環境を使ってOK」と言われると、つい共有環境のままテストを流したくなる。これも事故の元。
レビュアーから入った要件はこうだった。
テスト期間中はテスト実施者しかログインできない状態にする。管理できないなら全員分のパスワードを変えてしまうとか、そこまではしなくても良いが、そうしないと確実性に欠ける。 バッチも止まっていることを確認する。プロセスを全て監視する。もし、止められないなら、バッチ動作時間帯を避けるか、逆に意図的にバッチ負荷をかけた状態で性能を測る。どちらにせよ、計画的にスケジュールを引く必要がある。
これを最初に決めていないと、「測ったけど他のユーザーの引当処理が混ざっていた」「バッチが偶然走ってDB CPUがスパイクした」みたいなノイズが入って、全部やり直しになる。
やらかし6: 監視メトリクスをCloudWatchの初期画面だけで済ませようとした
AWS CloudWatchを開けばCPU使用率は見える。が、性能テストで本当に欲しいのは以下だ。
- EC2: CPU使用率(複数インスタンスのうちどれか)、メモリ使用率、ディスクI/O、ディスク使用率
- RDS: CPU、メモリ、DBコネクション数(最大値・平均値)、スロークエリ数
- ALB: スループット、レスポンスタイム、5xxエラー率
このうちメモリ使用率とディスク使用率はデフォルトでは取れない。CloudWatch Agentをインスタンス側にインストールして送信設定しないと、性能テスト中にメモリリークが起きていても気づけない。
また、「平均値」の取り方も注意がいる。5分単位の平均なのか、テスト全期間の平均なのか、ピーク値を別途取るのか、基準を決めておかないと、後で確認した際に、比較できず、全部やり直すことになる。
じゃあ何から始めるべきだったのか
仕切り直した手順をメモしておく。
Step 1: 仕様書の階層を再構成する
業務フローを「テストシナリオ」と「テストケース」に分解し直す。要件番号と対応付ける。AIを使っても、この工程だけで1〜2日かかる前提で見積もる。
Step 2: シナリオが書けない部分は、なるべく現場に近い人に聞く
「Web業務とは具体的にどの画面・どの操作を指すのか」「同時接続100人のうち何人がWeb、何人がハンディか」など、自分で決められないものは現場を把握している人にエスカレーションする。勝手に推測しない。
Step 3: テスト対象APIを特定し、画面のスクショと一緒に並べる
「画面上のどのボタンが、どのAPIを呼ぶのか」を全部紐づける。WebならChrome DevToolsのNetworkタブを開きながら手動で1周する地道な作業。
ハンディの場合、高いコードリーディングスキルが求められるし、プロキシツール(Chrome DevToolsのNetworkタブ相当)を入れないとデバッグは難しいかも。
Step 4: テストデータを「中身まで」確認する
事前作成されたデータをSQLで確認。件数、在庫数、カスタマイズテーブルの整合性をチェック。足りなければ追加投入する工数を確保する。
Step 5: 環境を独占する段取りを取る
該当環境のパスワードを全員分変更、バッチのスケジュールを把握、テスト時間帯をカレンダーで押さえる。
Step 6: 監視を整える
CloudWatch Agent投入、必要なダッシュボードを事前作成、メトリクスのサンプリング間隔を決める。
Step 7: ここでようやくJMeter
シナリオ1個ぶんのテストプランを作る。Git管理する(性能テストのスクリプトは資産になるので使い捨てにしない)。1シナリオを完走させてから、次のシナリオはコピーして差分だけ書き換える。
工数感の話
経験的に、性能テストは同等機能の単体テストの5〜10倍の工数がかかる。3人日で作った機能の単体テストが1人日なら、性能テストは少なくとも5人日見ておく必要がある。
これは「JMeterが難しいから」ではなく、
- 前提データの準備
- 結果の妥当性検証(数字が出ても、それが正しい負荷の結果かを別途確認)
- 環境隔離・スケジューリング
- メトリクス取得とレポート化
- 再度やり直す場合はデータをリセット
が全部上乗せで効いてくるからだ。「短納期で初回の性能テスト」は、ほぼ必ずシナリオを縮めるか期限を延ばすかの判断になる。
まとめ
初めての性能テストで一番やってはいけないのは、「JMeterの使い方を覚えれば進められる」と思い込むことだった。実際にはJMeterは最終工程のツールでしかなく、その前段の「テスト戦略 → シナリオ → ケース」の整理にこそ時間がかかる。
次に性能テストを任されたら、自分は以下を最初の1日でやる。
- テスト仕様書の階層をシナリオ/ケースに分解
- 仕様の穴を全部洗い出してエスカレーション
- 「期限内に何ができて何ができないか」を明確に伝える
- 結果を出す約束ではなく、実現可能な範囲を決める約束をする
「無理な結果出しよりも、実現可能な範囲の特定が最優先」。これが今回の最大の学びだった。
そしてこの学びは性能テストに限らない。「初めての領域 × 短納期」が揃った案件では、結果を出す約束を「実現可能な範囲を決める約束」に置き換える。 最初の1日で「できること / できないこと / 誰かに決めてもらうこと」の3つに仕分けして合意を取る。約束の対象を成果から範囲に変えるだけで、見えない破綻は見える計画に変わる。