ravineport blog

日々の学びをつらつらと

Gatlingのexec { session => ???}, jsonPathではまったこと

Gatlingとは?

https://gatling.io/

負荷テストのためのツール。Scalaで書くことができる。うれしい。

ここではGatlingを書いていくなかではまったことを書いていく。 

1. exec { session => ???} ではリクエストは投げられない

execメソッドの基本的な使い方は以下の通り。

exec {
  http("テストリクエスト")
    .get("/users") // /usersにGETリクエストを投げる
}

しかし、以下の場合は実際に/usersにリクエストは投げられない。

exec { session =>
  http("テストリクエスト")
    .get("/users") // 実行時にリクエストが投げられない!
 session // Session型を返すようにしないとコンパイルエラー
}

execにsessionを受け取る関数を渡す場合は、リクエストを投げる処理は書かないようにする。

なぜこのようなことをしようとしたかというと、http("テストリクエスト").get("/users")を関数にしてかつSessionに保存された値をリクエストパラメータとして使おうとしたため。 次のようなことをしようとした。

def usersRequest(session: Session): HttpRequestBuilder = {
  http("テストリクエスト")
    .get("/users")
    .queryParam("id", session.get("userId"))
}

exec { session =>
  usersRequest(session) // リクエストは投げられない
  session
}

この場合は以下のようにすればよい

def usersRequest(): HttpRequestBuilder = {
  http("テストリクエスト")
    .get("/users")
    .queryParam("id", "${userId}")
}

exec {
  usersRequest(session)
}

sessionを渡していないのにどこかに保存されているのであろうsessionの内容にアクセスできてしまうことに個人的には気持ち悪さを感じるが、そこはGatlingのお作法ということで。

2. レスポンスJSONからjsonPathメソッドを使って値を取り出すときは、一度Sessionに保存すること

レスポンスJSONが期待するものかどうかを確認するには以下のように書く。

http("request")
...
.check(jsonPath("$..result").exists) // 返ってきたJSONが{"result": ...}であるかどうかチェック

resultキーに対する値(Int型)を取り出してなにかしら処理をしたい場合に以下のように書いたがうまく値を取り出せなかった。

http("request")
...
.check {
  val result = jsonPath("$..result").ofType[Int] // resultに期待した値が入らない
}

値を取り出したい場合は一度Sessionに保存することでうまくいった。

http("request")
...
.check {
  jsonPath("$..result").ofType[Int].find.saveAs("result")
}

// ↑のあと次のように取り出せる
exec { session =>
  val result = session("result").as[Int]
}

がんばればjsonPathから値を取り出すこともやろうと思えばできるらしい。

参考:scala - How do I retrieve a value from a JSON string using gatling JsonPath.query? - Stack Overflow

import com.fasterxml.jackson.databind.ObjectMapper

http("request")
  .check {
    val json = """{"id":"derp"}"""
    val parsed = new ObjectMapper().readValue(json, classOf[Object])
    
    // to retrieve the ids as a list:
    val ids = JsonPath.query("$.id", parsed).right.get.toList
    
    // the only "id" result of the query
    val id = ids.head
}