Reputation: 59
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
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.
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
andsetAll
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