🧪

k6で始めるパフォーマンステスト

2024/12/03に公開

はじめに

今年新卒で入社し、エンジニアとして働き始めた中西です。
パフォーマンステストを行っていく中でk6の良さを知ったので、共有します。

パフォーマンステストとは

全体を通して速度や品質などの性能がどの程度かを測るテストのことです。
ボトルネックを発見し、修正することでソフトウェアの品質を高めることができます。
有名なテストに、負荷テスト、ストレステスト、スパイクテストなどがあります。

k6とは

概要

k6とは、オープンソースの負荷テストツールです。
パフォーマンステストを毎回手動でやっていては面倒に感じられるものでもあります。そんな中でも、k6であれば自動化することができます。そのため、ソフトウェアの更新があった場合に、k6でパフォーマンステストを作ってさえおけば、問題点をすぐに発見でき、品質の向上につなげられるというわけです。

メリット

k6ならではの強みとして以下があります。

  • 軽量にテストを動作させられること
  • ローカルでもクラウドでも実行可能であること
  • JavaScriptでテストシナリオを作成できること
  • 豊富なドキュメントが存在すること

デメリット

k6はテストシナリオをJavaScriptを用いて実装するため、GUIではパフォーマンステストを作成することができません。特にGUIでパフォーマンステストを作成したい場合などは、k6よりもJMeterを使用することをおすすめします。

重要だと感じたこと

テスト作成時に知っておくべきこと

  1. 仮想ユーザーとオプション
    テストシナリオの重要な要素で、これらを組み合わせることで思い通りにテストを動作させられるようになります。

    • 仮想ユーザー
      • k6ではVUともいわれる
      • optionsメソッドや実行時に設定できる
      • コード例
      /**
       * 1名の仮想ユーザーが1回テストを実行する
       */
      export const options = {
          // 仮想ユーザー数:1名
          vus: 1,
          // テスト反復数:1回
          iterations: 1,
      }
      
    • オプション
      • テストの動作(テストシナリオ)を決めるもの
      • optionsメソッドで実装する
      • コード例
      /**
       * 各仮想ユーザーが10回ずつテストを実行する
       */
      export const options = {
          scenarios: {
              per_vu_iterations_scenario: {
                  // シナリオの設定:仮想ユーザーごとに決められた反復数テストを実行するシナリオ
                  executor: 'per-vu-iterations',
                  // 仮想ユーザー数:10名
                  vus: 10,
                  // テスト反復数:10回
                  iterations: 10,
                  // 最大テスト実行時間:5分間
                  maxDuration: '5m',
              },
          },
      }
      
  2. ライフサイクル
    テストを設計する上で重要な要素です。私は最初にこれを知らずに作成しており、テストの実行に失敗していました。

    段階 サイクル名 呼ばれる回数 必須か
    初期化 コンテキスト(init) VU毎に1回 Yes
    準備 setup 全体で1回 No
    テスト default 反復ごとか、オプションで設定している回数だけ Yes
    終了後 teardown 全体で1回 No
    その他 handleSummary 全体で1回 No

    コード例

    export const options = {
        // シナリオの設定
    }
    
    export const setup = () => {
        // テストの前処理
    }
    
    export default ()=> {
        // テスト
    }
    
    export const teardown = () => {
        // テストの後処理
    }
    
    export const handleSummary = (data) => {
        // カスタムメトリクスを出力
    }
    
  3. メトリクス
    メトリクスを知ることで、リリース前にボトルネックを発見し、問題の原因を特定・修正へとつなげることができます。それにより、リリース後も前と変わらない状態を維持できるため、私はテスト終了後の評価が最も大事だと考えています。

  • 最終的な結果で、計測されたものが出力される
  • 表示結果例
     data_received..................: 22 kB 5.7 kB/s
     data_sent......................: 742 B 198 B/s
     http_req_blocked...............: avg=1.05s    min=1.05s    med=1.05s    max=1.05s    p(90)=1.05s    p(95)=1.05s
     http_req_connecting............: avg=334.26ms min=334.26ms med=334.26ms max=334.26ms p(90)=334.26ms p(95)=334.26ms
     http_req_duration..............: avg=2.7s     min=2.7s     med=2.7s     max=2.7s     p(90)=2.7s     p(95)=2.7s
       { expected_response:true }...: avg=2.7s     min=2.7s     med=2.7s     max=2.7s     p(90)=2.7s     p(95)=2.7s
     http_req_failed................: 0.00% ✓ 01
     http_req_receiving.............: avg=112.41µs min=112.41µs med=112.41µs max=112.41µs p(90)=112.41µs p(95)=112.41µs
     http_req_sending...............: avg=294.48µs min=294.48µs med=294.48µs max=294.48µs p(90)=294.48µs p(95)=294.48µs
     http_req_tls_handshaking.......: avg=700.6ms  min=700.6ms  med=700.6ms  max=700.6ms  p(90)=700.6ms  p(95)=700.6ms
     http_req_waiting...............: avg=2.7s     min=2.7s     med=2.7s     max=2.7s     p(90)=2.7s     p(95)=2.7s
     http_reqs......................: 1     0.266167/s
     iteration_duration.............: avg=3.75s    min=3.75s    med=3.75s    max=3.75s    p(90)=3.75s    p(95)=3.75s
     iterations.....................: 1     0.266167/s
     vus............................: 1     min=1      max=1
     vus_max........................: 1     min=1      max=1
    
  • 出力結果をカスタムするにはhandleSummaryメソッドを利用する

つまづいたポイント

  • Node.jsのライブラリは使用できないこと
    • OSモジュールを用いたCPU使用率やメモリー使用率の測定はできない
  • コンテキスト内(init)で、VU間共有の変数は使用できないこと
    • コンテキストはVU毎に1回呼ばれるため

TIPS

まとめ

k6はJavaScriptで手軽に作成できるため、テストの迅速な実施と運用を行えます。なによりも、AWSやCI/CDパイプラインとの高い親和性があります。クラウド環境や自動化プロセスにも組み込みやすく、開発サイクル全体の効率を向上させることができます。そのため、k6を使えば、ソフトウェアの信頼性と品質を向上させることができるでしょう。

参考

WealthNavi Engineering Blog

Discussion