皆さんこんにちは、QA部門のカヤ(@kareyama_r)です。
この記事はソフトウェアテスト Advent Calendar 2020の16日目です。
つい先日、ソフトウェアテスト自動化カンファレンス2020が開催され、テスト自動化に関する様々な取り組みやフレームワークが紹介されていましたね!
私のイチオシのフレームワークは、去年・一昨年と同カンファレンスで取り上げられたKarateですが、今年は話題に上がっていなかったので取り上げたいと思います。
最初はAPI試験用のフレームワークとして発表されたKarateですが、最近は負荷試験やUI試験自動化までカバーするようになっています。
今回はこれらの機能を一気に試してみよう!ということで、アプリに負荷をかけながら、画面のロード時間を計測するという内容でKarateを使ってみました。
対象アプリとしてElastic Stackを使用します。
DBとなるElasticsearch・BIツールのKibanaを立ち上げて、Elasticsearchに負荷をかけつつKibanaへのレスポンスの影響を確認します。
以下が構成イメージです。
セットアップ
まずは試験環境の準備です。Docker上にElasticsearch・Kibanaを立ち上げます。
$ docker pull elasticsearch:7.9.3 $ docker pull kibana:7.9.3 $ docker network create es-network $ docker run -d --name elasticsearch --net es-network -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.9.3 $ docker run -d --name kibana --net es-network -p 5601:5601 kibana:7.9.3
localhost:5601
にアクセスし、サンプルデータをインポートします。
今回はSample web logs
にしました。
カッコいいダッシュボードをローカル環境に立てられました。 現時点でリロードに2~3秒かかり、データプロット数も多いので、イジメがいがありそうですね😎
次に、Karateプロジェクトを用意します。 今回はKarate gatlingのサンプルプロジェクトを雛形として利用します。 https://github.com/intuit/karate/tree/master/examples
このプロジェクトに以下の3つを作成していきます。
- Elasticsearchの
_search API
へリクエストを送るKarate Feature - のScenarioを多重実行してElasticsearchに負荷をかけるKarate Gatling Simulation
- Karate DriverでChromeを操作し、Kibana Dashboardのロード時間を計測するKarate UI Feature
Karate Feature作成
Karateの基本機能であるAPIリクエストを使用し、Docker上に立ち上げたElasticsearchにリクエストを送ります。
Elasticsearchに負荷がかかるような、ある程度複雑なリクエストクエリを用意し、Karateのデータドリブン機能で読み込みます。
Feature: Elasticsearchへのリクエスト Background: * url 'http://localhost:9200' Scenario Outline: Visualizeデータ取得 Given path 'kibana_sample_data_logs/_search' And request read('<filename>') When method get Then status 200 Examples: | filename | | TotalRequestsAndBytes.json | | UniqueVisitorsAverageBytes.json | | Heatmap.json |
データドリブンでは、Examples:
で定義した値(今回はJSONファイル名)を変数(filename
)に順に代入してScenarioを実行してくれます。
上記のコードでは、ファイル内容を読み込んでそのままリクエストボディとして使用しています。
検証として、レスポンスコードが200であることをチェックします。
Karate Gatling Simulation作成
次に、先ほど作成したFeatureファイルを多重実行して負荷をかけるようにします。
これはGatlingの機能を使用しているため、Scalaを使って記述します。
Scalaに明るくない自分でも、サンプル見つつ簡単に実装できました。
package gatling import com.intuit.karate.gatling.PreDef._ import io.gatling.core.Predef._ import scala.concurrent.duration._ class SearchSimulation extends Simulation { val protocol = karateProtocol() protocol.nameResolver = (req, ctx) => req.getUrlAndPath() val search = scenario("search").exec(karateFeature("classpath:scenario/elasticsearch/search.feature")) setUp( search.inject(rampUsersPerSec(10) to 100 during(1 minutes)).protocols(protocol) ) }
karateFeature
メソッドで読み込んでいるsearch.feature
が、先ほど作成したFeatureファイルです。
これを、1分かけて10から100まで秒間アクセス数が上がるように設定しました。
一旦ここまでで負荷試験は可能になったので、実行してみましょう。 Mavenプロジェクトとして以下のコマンドで起動します。
mvn clean test-compile gatling:test
しばらく待つと実行完了し、Gatlingレポートが出力されます。以下抜粋。
_search API
が累計約1万回呼び出され、全て実行に成功した(ステータスコードが200だった)ことが分かります。
時間をが経つにつれActive Users(≒リクエスト数)が増え、それにほぼ比例してレスポンスが遅くなっていることが分ります。
これでDB側への負荷試験の準備は完了です。 次は画面側となるKibanaで、ユーザがデータ表示にどれくらい待たされるかを計測していきます。
Karate UI Feature作成
Kibanaの仕様として、データのロード中は画面上部に細いピンク色のバーが表示されます。
つまり。ダッシュボードを開いた、もしくはダッシュボード再描画ボタンを押した時から、 このピンク色のバーが非表示になった時までが、ダッシュボードのロードにかかった時間と考えられます。
これをKarate UIで計測してみましょう。以下のコードになります。
Feature: Access Kibana Background: * configure driver = { type: 'chrome', showDriverLog: true } * configure retry = { count: 10, interval: 3000 } * def getSysTime = """ function(){ return java.lang.System.currentTimeMillis() } """ * def calcDuration = """ function(startTime){ var endTime = java.lang.System.currentTimeMillis(); var diff = endTime - startTime; return (diff / 1000) } """ Scenario: Kibana Dashboard 計測 Given driver 'http://localhost:5601/app/dashboards#/list' And waitForEnabled('{a}[Logs] Web Traffic').click() When waitForText('span.euiBreadcrumb', '[Logs] Web Traffic') And def startTime = getSysTime() Then waitUntil('div.kbnLoadingIndicator', "_.className.includes('hidden')") * print 'Duration:', calcDuration(startTime) * delay(15000) When click('{span}Refresh') And def startTime = getSysTime() Then waitUntil('div.kbnLoadingIndicator', "_.className.includes('hidden')") * print 'Duration:', calcDuration(startTime) # 以下繰り返し
Background:
ではWebドライバーの設定と計測用の関数の定義を行っています。
Scenario:
からがブラウザ操作です。
最初の計測は、ダッシュボードを開いてヘッダー文字列の「[Logs] Web Traffic」が表示されたタイミングで開始しています。
2回目の計測は、ダッシュボードのRefresh
ボタンが押されたタイミングで開始します。
計測を終了タイミングは共通で、ピンク色のバーが非表示になった時とします。
div.kbnLoadingIndicator
がピンクのロードバーを指しています。
これがhidden
クラスを持つと非表示になります。
実行
それではいよいよ実行です。 Karate UI Featureを実行して、Kibanaでのロード時間を15秒おきに表示しておき、Karate Gatling Simulationを実行してElasticsearchに負荷をかけていきます。
そして出てきた計測結果がこちらです。
01:01:26.558 [main] INFO com.intuit.karate - [print] Duration: 6.958 01:01:45.472 [main] INFO com.intuit.karate - [print] Duration: 3.408 01:02:07.238 [main] INFO com.intuit.karate - [print] Duration: 6.427 01:02:29.290 [main] INFO com.intuit.karate - [print] Duration: 6.649 01:02:54.966 [main] INFO com.intuit.karate - [print] Duration: 9.819
初期のロードが長く、その後負荷がかかるにつれて重くなり、最後にはロードに10秒近くかかっていたことがわかります。
もう少し長い時間をかけるとどうなるかも知りたかったのですが、これ以上実行時間を伸ばすと、Socketの使い過ぎでKarateにElasticsearchが応答しなくなりました(-_-;)
Windowsマシンでやるには限度があるようです。
まとめ
Karateの負荷試験とUI試験機能を使ってみました。
どちらもかなりシンプルな記述で実装できるのがありがたく、またJavaやJS関数を呼び出して複雑な処理もできるのが頼もしいです。
Karate UIは今年出たばかりの機能のため、大御所のSeleniumに比べると機能が少ない印象ですが、書き方が簡潔で、サンプルプロジェクトに数行書き足すだけですぐ動くのが嬉しいなと感じました。
これからもまだまだ進化していくと思うので、動向を追っていきたいと思います。
Acroquest Technologyでは、キャリア採用を行っています。
- ディープラーニング等を使った自然言語/画像/音声/動画解析の研究開発
- Elasticsearch等を使ったデータ収集/分析/可視化
- マイクロサービス、DevOps、最新のOSSを利用する開発プロジェクト
- 書籍・雑誌等の執筆や、社内外での技術の発信・共有によるエンジニアとしての成長
少しでも上記に興味を持たれた方は、是非以下のページをご覧ください。
【データ分析】 Kaggle Masterと働きたい尖ったエンジニアWanted! - Acroquest Technology株式会社のデータサイエンティストの求人 - Wantedlywww.wantedly.com