前回の記事では「k6 new」で雛形を作れることは説明しましたが、処理のほとんどを自分で記述していく必要があります。Javascriptが得意な方はそれほど問題にはならないでしょうが、Javascript初心者にとってはその言語を使えるようになることが、k6を使い始めるために超えなければいけない壁となってしまいます。
そこで今回はブラウザからぽちぽちでコードをジェネレートする方法をご紹介します。
har-to-k6
har-to-k6とは、HAR(HTTP Archive File)ファイルをコンバートしてk6のシナリオをジェネレートするCLIツールです。ある操作をレコーディングしてHARを出力し、har-to-k6でJavascriptにコンバートしてストレステストを実行する、といったように、処理のほとんどをツールによってジェネレートできます。
試す
HARはChromeやFirefoxのDevToolsからダウンロード可能なので簡単に試してみましょう。
har-to-k6のインストール
GitHub - grafana/har-to-k6: JSON config representation of K6 script
インストール方法はこちらに書かれている通りです。
Dockerで起動してもいいですし、npmでインストールしてもOKです。今回はnpmでインストールしたツールを使用します。
サンプルアプリを用意
こちらのサンプルアプリを使用します。アプリケーションの起動にはDockerが必要になるので、事前にインストールしておきます。
Developmentに実行方法が書かれているので、その通りに実行します。
起動が完了するとhttp://localhostにアクセスすればTodo Appが表示されるはずです。
HARを出力
[F12]キーかメニューを辿って「デベロッパーツール」を起動してください。
デベロッパーツールの「Network」パネルに移動します。
Networkパネルでは、現在表示中のWebページのHTTPリクエストが見られます。すでに何かしらのHTTPリクエストが記録されている場合はレコーディングを一度停止しておきましょう。
↓↓↓
黒マルになっていればレコーディング停止状態です。
再度レコーディングボタンをクリックし、レコーディングを開始します。
「New Item」と書かれてテキストボックスに何かしらも文字を入力し「Add Item」ボタンをクリックします。
いくつかアイテムを追加したらHARファイルをダウンロードします。
私の場合は「localhost.har」というファイル名でダウンロードされました。
コンバート
それでは実際に「localhost.har」をk6のシナリオにジェネレートしてみます。
$ har-to-k6 localhost.har info: Converting 'localhost.har' info: Wrote k6 script to 'loadtest.js'
「loadtest.js」というファイルが出力されました。
中身を確認してみるとk6のシナリオであることがわかります。http.postで先ほど入力した文字列などがポストされているのではないでしょうか。
実行
それでは実行してアイテムが追加されるか確認してみましょう。
k6の実行前にTodo Appに追加されたアイテムを一度削除してしまった方がわかりやすいかもしれません。
$ k6 run loadtest.js
エラーなく完了しました。
ブラウザを確認すると、たしかに先ほど追加したアイテムが再度追加されています。
loadtest.jsにはoptionsが設定されています。試しにvusなどを設定してみます。
diff --git a/loadtest.js b/loadtest.js index 080d43f..d218d38 100644 --- a/loadtest.js +++ b/loadtest.js @@ -3,7 +3,10 @@ import { sleep } from 'k6' import http from 'k6/http' -export const options = {} +export const options = { + vus: 2, + duration: '5s' +} export default function main() { let response
これで再度実行すると・・・
いい感じです。
このままでは「test1」「test2」が何度も追加されるだけなので面白くありません。そこで何度目のIterationなのかを取得できる「exec.vu.iterationInInstance」をアイテム名の末尾に追加してみます。
diff --git a/loadtest.js b/loadtest.js index 080d43f..2a9c187 100644 --- a/loadtest.js +++ b/loadtest.js @@ -2,34 +2,17 @@ import { sleep } from 'k6' import http from 'k6/http' +import exec from 'k6/execution'; -export const options = {} +export const options = { + vus: 2, + duration: '5s' +} export default function main() { let response - response = http.post('http://localhost/api/items', '{"name":"test1"}', { - headers: { - Accept: '*/*', - 'Accept-Encoding': 'gzip, deflate, br, zstd', - 'Accept-Language': 'ja,en-US;q=0.9,en;q=0.8', - Connection: 'keep-alive', - 'Content-Type': 'application/json', - Host: 'localhost', - Origin: 'http://localhost', - Referer: 'http://localhost/', - 'Sec-Fetch-Dest': 'empty', - 'Sec-Fetch-Mode': 'cors', - 'Sec-Fetch-Site': 'same-origin', - 'User-Agent': - 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36', - 'sec-ch-ua': '"Google Chrome";v="131", "Chromium";v="131", "Not_A Brand";v="24"', - 'sec-ch-ua-mobile': '?0', - 'sec-ch-ua-platform': '"macOS"', - }, - }) - - response = http.post('http://localhost/api/items', '{"name":"test2"}', { + response = http.post('http://localhost/api/items', JSON.stringify({name: "test" + String(exec.vu.iterationInInstance)}), { headers: { Accept: '*/*', 'Accept-Encoding': 'gzip, deflate, br, zstd',
loadtest.jsの末尾には1秒のスリープが入っているので1秒に1回を2VUsが実行します。これを5秒なので10回のリクエストが飛んでいればOKです。
実行します。
アイテムは10個、2VUsのIterationは5回(のはず)なので・・・あってそうですね。
まとめ
ブラウザの操作から簡単にシナリオを作ることができました。optionsは空の状態なので、何度繰り返す必要があるのか、どれくらいの負荷をかけるのかなどは自分で調整する必要があります。また、同じ操作を繰り返すので毎回入力する文字を変えたりユーザーを変える必要がある場合にも少し改造が必要です。とはいえ、ここまでジェネレートできていればOKですね。
※くれぐれも人様のWebサイトには迷惑をかけないようにしましょう!