har123
har123

Reputation: 59

Gatling Rest API Testing - retrieve a value from json response and add it to the list, iterate through list

I am new to Gatling, I am trying to do the performance testing for couple of rest calls. In my scenario I need to extract a value from json response of the 1st call and add those values to the list after looping for few times. Again after looping for few times and adding the values into the list, I want to reuse each value in my next rest call by iterating over the values in the list. Can anyone please suggest on how to implement this. I tried something as below,

    var datasetIdList = List.empty[String]
    val datasetidsFeeder = datasetIdList.map(datasetId => Map("datasetId" -> datasetId)).iterator
    
    def createData() = {
      repeat(20){
      feed("").exec(http("create dataset").post("/create/data").header("content-type", "application/json")
            .body(StringBody("""{"name":"name"}"""))
            .asJson.check(jsonPath("$.id").saveAs("userId"))))
.exec(session => { var usrid = session("userId").as[String].trim
          datasetIdList:+= usrid session})
    }}
    def upload()= feed(datasetidsFeeder).exec(http("file upload").post("/compute-metaservice/datasets/${datasetId}/uploadFile")
            .formUpload("File","./src/test/resources/data/File.csv")
            .header("content-type","multipart/form-data")
            .check(status is 200))
  
    val scn = scenario("create data and upload").exec(createData()).exec(upload())
    setUp(scn.inject(atOnceUsers(1))).protocols(httpConf)
    }

I am seeing an exception that ListFeeder is empty when trying to run above script. Can someone please help

Updated Code:

class ParallelcallsSimulation extends Simulation{

  var idNumbers = (1 to 50).iterator

  val customFeeder = Iterator.continually(Map(
    "name" -> ("test_gatling_"+ idNumbers.next())
  ))

  val httpConf = http.baseUrl("http://localhost:8080")
    .header("Authorization","Bearer 6a4aee03-9172-4e31-a784-39dea65e9063")

  def createDatasetsAndUpload() = {
    repeat(3) {
      //create dataset
      feed(customFeeder).exec(http("create data").post("/create/data").header("content-type", "application/json")
        .body(StringBody("""{ "name": "${name}","description": "create data and upload file"}"""))
        .asJson.check(jsonPath("$.id").saveAs("userId")))
        .exec(session => {
          val name = session("name").asOption[String]
          println(name.getOrElse("COULD NOT FIND NAME"))
          val userId = session("userId").as[String].trim
          println("%%%%% User ID ====>"+userId)
          val datasetIdList = session("datasetIdList").asOption[List[_]].getOrElse(Nil)
          session.set("datasetIdList", userId :: datasetIdList)
        })
    }
  }
 // File Upload
  def fileUpload() = foreach("${datasetIdList}","datasetId"){
    exec(http("file upload").post("/uploadFile")
      .formUpload("File","./src/test/resources/data/File.csv")
      .header("content-type","multipart/form-data")
      .check(status is 200))
  }

  def getDataSetId() = foreach("${datasetIdList}","datasetId"){
      exec(http("get datasetId")
        .get("/get/data/${datasetId}")
        .header("content-type","application/json")
        .asJson.check(jsonPath("$.dlp.dlp_job_status").optional
        .saveAs("dlpJobStatus")).check(status is 200)
      ).exec(session => {
        val datastId = session("datasetId").asOption[String]
        println("request for datasetId >>>>>>>>"+datastId.getOrElse("datasetId not found"))
        val jobStatus = session("dlpJobStatus").asOption[String]
        println("JOB STATUS:::>>>>>>>>>>"+jobStatus.getOrElse("Dlp Job Status not Found"))
        println("Time: >>>>>>"+System.currentTimeMillis())
        session
      }).pause(10)
    }

  val scn1 = scenario("create multiple datasets and upload").exec(createDatasetsAndUpload()).exec(fileUpload())
  val scn2 = scenario("get datasetId").pause(100).exec(getDataSetId())

  setUp(scn1.inject(atOnceUsers(1)),scn2.inject(atOnceUsers(1))).protocols(httpConf)
}

I see below error when I try to execute above script [ERROR] i.g.c.s.LoopBlock$ - Condition evaluation crashed with message 'No attribute named 'datasetIdList' is defined', exiting loop

Upvotes: 0

Views: 1393

Answers (1)

George Leung
George Leung

Reputation: 1552

var datasetIdList = List.empty[String] defines a mutable variable pointing to a immutable list.

val datasetidsFeeder = datasetIdList.map(datasetId => Map("datasetId" -> datasetId)).iterator uses the immutable list. Further changes to datasetIdList is irrelevant to datasetidsFeeder.


Mutating a global variable with your virtual user is usually not a good idea. You can save the value into the user's session instead.


In the exec block, you can write:

val userId = session("userId").as[String].trim
val datasetIdList = session("datasetIdList").asOption[List[_]].getOrElse(Nil)
session.set("datasetIdList", userId :: datasetIdList)

Then you can use foreach to iterate them all without using a feeder at all.

foreach("${datasetIdList}", "datasetId") {
  exec(http("file upload")
    ...
}

You should put more work in your question.

  • Your code is not syntax-highlighted, and is formatted poorly.
  • You said "I am seeing an exception that ListFeeder is empty" but the words "ListFeeder" are not seen anywhere.
  • You should post the error message so that it's easier to see what went wrong.

In the documentation linked, there is a Warning. Quoted below:

Session instances are immutable!

Why is that so? Because Sessions are messages that are dealt with in a multi-threaded concurrent way, so immutability is the best way to deal with state without relying on synchronization and blocking.

A very common pitfall is to forget that set and setAll actually return new instances.

This is why the code in the updated question doesn't update the list.

session => {
  ...
  session.set("datasetIdList", userId :: datasetIdList)
  println("%%%% List =====>>>" + datasetIdList.toString())
  session
}

The updated session is simply discarded. And the original session is returned in the anonymous function.

Upvotes: 1

Related Questions