JMeter の基本概念

コンポーネント役割
Thread Group仮想ユーザー数・ランプアップ時間・繰り返し数を定義するテストの基本単位
HTTP Request SamplerHTTP リクエストを定義(URL・メソッド・パラメータ・ボディ)
Response Assertionレスポンスコード・テキスト・レスポンスタイムを検証
Summary Reportスループット・エラー率・平均/最大/90th パーセンタイルを集計
CSV Data Set Configテストデータを CSV から読み込んでリクエストに埋め込む
Constant Timerリクエスト間に待機時間を設定(実際のユーザー行動に近づける)

JMX ファイルでのテスト計画定義

JMeter の GUI は視覚的ですが、CI では JMX(XML)ファイルをバージョン管理してコマンドラインで実行します。主要な設定値を解説します。

<!-- user-api-load-test.jmx(主要部分抜粋) -->
<jmeterTestPlan version="1.2">
  <hashTree>
    <TestPlan testname="User API 負荷テスト">
      <hashTree>

        <!-- ─ スレッドグループ設定 ─ -->
        <ThreadGroup testname="通常負荷シナリオ">
          <stringProp name="ThreadGroup.num_threads">50</stringProp>  <!-- 仮想ユーザー数 -->
          <stringProp name="ThreadGroup.ramp_time">30</stringProp>    <!-- 30 秒かけて立ち上げ -->
          <stringProp name="ThreadGroup.duration">120</stringProp>    <!-- 120 秒間実行 -->
          <boolProp   name="ThreadGroup.scheduler">true</boolProp>
          <hashTree>

            <!-- ─ HTTP リクエスト ─ -->
            <HTTPSamplerProxy testname="GET /api/users">
              <stringProp name="HTTPSampler.domain">${HOST}</stringProp>
              <intProp    name="HTTPSampler.port">8080</intProp>
              <stringProp name="HTTPSampler.path">/api/v1/users</stringProp>
              <stringProp name="HTTPSampler.method">GET</stringProp>
            </HTTPSamplerProxy>

            <!-- ─ レスポンスアサーション ─ -->
            <ResponseAssertion testname="ステータスコード 200">
              <intProp name="Assertion.test_type">8</intProp>  <!-- 8 = equals -->
              <collectionProp name="Asserion.test_strings">
                <stringProp>200</stringProp>
              </collectionProp>
              <stringProp name="Assertion.test_field">Assertion.response_code</stringProp>
            </ResponseAssertion>

          </hashTree>
        </ThreadGroup>

      </hashTree>
    </TestPlan>
  </hashTree>
</jmeterTestPlan>

JMeter CLI 実行とレポート生成

# JMeter のインストール(Homebrew 例)
brew install jmeter

# ── コマンドライン実行 ──
jmeter -n   -t tests/load/user-api-load-test.jmx   -l results/result.jtl   -e -o reports/load-test-report/   -JHOST=localhost   -JPORT=8080

# オプション説明
# -n        : GUI なし(コマンドラインモード)
# -t        : JMX ファイルのパス
# -l        : 結果ファイル(JTL)の出力先
# -e -o     : HTML ダッシュボードレポートの生成と出力先
# -JHOST    : JMX 内の変数 ${HOST} に値を設定

# ── Docker での実行(CI 推奨) ──
docker run --rm   -v $(pwd)/tests/load:/load   -v $(pwd)/reports:/reports   justb4/jmeter:5.6.3   -n -t /load/user-api-load-test.jmx   -l /reports/result.jtl   -e -o /reports/html/

結果分析の指標

指標意味一般的な合否基準
スループット(Throughput)単位時間あたりのリクエスト数(req/sec)要件値以上
平均レスポンスタイム全リクエストの平均応答時間1,000ms 以下(要件による)
90th パーセンタイルリクエストの 90% がこの時間以内に完了2,000ms 以下(一般的目安)
エラー率(Error Rate)失敗したリクエストの割合0.1% 以下
最大レスポンスタイム最も遅かったリクエストの応答時間タイムアウト設定値未満

⚠️ 平均値よりパーセンタイルを重視する

平均レスポンスタイムは一部の超高速リクエストに引き下げられることがあります。ユーザー体験の評価には 90th・95th パーセンタイルを主要指標として使用してください。

OWASP ZAP の仕組み

OWASP ZAP(Zed Attack Proxy)はプロキシとして動作し、アプリケーションへの HTTP リクエスト・レスポンスを傍受・分析してセキュリティの脆弱性を検出します。

スキャン種別内容用途
Baseline Scan(受動的)Spider でページを巡回し、アクティブ攻撃なしで脆弱性を検出CI/CD での毎回スキャン
Full Scan(能動的)SQL インジェクション・XSS 等を実際に試みる攻撃的スキャンリリース前・ステージング環境
API ScanOpenAPI / Swagger / GraphQL 仕様書からエンドポイントを列挙してスキャンREST API のセキュリティテスト

Baseline スキャン(受動的スキャン)

# Docker を使った ZAP Baseline スキャン(推奨)
docker run --rm   -v $(pwd)/reports:/zap/wrk/:rw   ghcr.io/zaproxy/zaproxy:stable   zap-baseline.py   -t http://host.docker.internal:8080 \   # スキャン対象 URL
  -r zap-baseline-report.html \           # HTML レポート
  -J zap-baseline-report.json \           # JSON レポート(CI パース用)
  -l WARN \                               # 警告以上を報告
  -I                                      # アラートがあっても終了コード 0(CI で失敗させない場合)

# ── よく検出される脆弱性カテゴリ ──
# - Missing Anti-CSRF Tokens(CSRF トークンなし)
# - X-Frame-Options Header Not Set(クリックジャッキング対策なし)
# - Content-Security-Policy Header Not Set(CSP ヘッダーなし)
# - Server Leaks Information via "X-Powered-By"(サーバー情報漏洩)
# - Cookie without Secure Flag Set(Secure 属性なし Cookie)

API スキャン(OpenAPI スペックから)

# OpenAPI 仕様書を使った API スキャン
docker run --rm   -v $(pwd)/reports:/zap/wrk/:rw   ghcr.io/zaproxy/zaproxy:stable   zap-api-scan.py   -t http://host.docker.internal:8080/v3/api-docs \  # OpenAPI JSON の URL
  -f openapi \                                        # フォーマット指定
  -r zap-api-report.html   -J zap-api-report.json   -z "-config replacer.full_list(0).description=Auth       -config replacer.full_list(0).enabled=true       -config replacer.full_list(0).matchtype=REQ_HEADER       -config replacer.full_list(0).matchstr=Authorization       -config replacer.full_list(0).replacement=Bearer\ YOUR_TOKEN"
# ↑ 認証が必要な API に Bearer トークンを挿入する設定

GitHub Actions 連携

# .github/workflows/security-and-load.yml
name: System Test — Load + Security

on:
  push:
    branches: [main]
  schedule:
    - cron: "0 2 * * *"   # 毎日 AM 2:00 に実行(深夜バッチ)

jobs:
  load-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Run JMeter load test
        run: |
          docker run --rm             -v ${{ github.workspace }}/tests/load:/load             -v ${{ github.workspace }}/reports:/reports             --network host             justb4/jmeter:5.6.3             -n -t /load/user-api-load-test.jmx             -l /reports/result.jtl             -e -o /reports/html/             -JHOST=localhost
      - name: Upload JMeter report
        uses: actions/upload-artifact@v4
        if: always()
        with:
          name: jmeter-report
          path: reports/html/

  security-scan:
    runs-on: ubuntu-latest
    needs: load-test   # 負荷テスト後に実行
    steps:
      - uses: actions/checkout@v4
      - name: ZAP Baseline Scan
        uses: zaproxy/action-baseline@v0.12.0
        with:
          target: "http://localhost:8080"
          rules_file_name: ".zap/rules.tsv"   # 無視ルールファイル
          cmd_options: "-I"                     # アラートで CI 失敗させない
      - name: Upload ZAP report
        uses: actions/upload-artifact@v4
        if: always()
        with:
          name: zap-report
          path: report_html.html

まとめ

  • JMeter のテスト計画は JMX ファイルでバージョン管理し、CLI + Docker で CI に組み込む
  • 性能目標はスループット・90th パーセンタイル・エラー率を基準に設定し、結果は HTML ダッシュボードで共有する
  • OWASP ZAP の Baseline スキャンは CI の毎実行に組み込み、Full/API スキャンはリリース前・ステージング環境で実施する
  • 認証が必要な API は ZAP の replacer 設定でトークンを自動付与してスキャンする
  • ZAP の誤検知は .zap/rules.tsv で個別にルールを無効化してノイズを管理する