Pritam Banerjee
Pritam Banerjee

Reputation: 18923

Why is this Gatling job not running sequentially?

What I am trying to do is:

  1. Make a GET call to get a list of id
  2. For all those ids make a series of another GET calls

Here is my code for that:

/** * Created by pbane3 on 11/10/16. */

import io.gatling.core.Predef._
import io.gatling.http.Predef._
import scala.concurrent.duration._
import scala.concurrent.forkjoin.ThreadLocalRandom
import scala.collection.mutable
import scala.collection.Map


class RunWithMePerfTest extends Simulation {

  var idList  = List[String]()

  var count = 0;

  def idFeeder(idString:String):Unit = {
    idList = idString.split(",").map(_.trim).toList;
    println(idList)
  }

  def getRunId() : String = {
     println(count)
     var id = idList(count);
     count = count+1;
     return id;
  }

  object GetAllRunDetails {

    val getAllRunDetails = exec(http("Get Run Ids")
      .get("**/**")
      .check(status in (200 to 209))
      // .check(bodyString.saveAs("GetResponse"))
      .check(jsonPath("$..id").ofType[String].findAll.transform(_.mkString(",")).saveAs("runId")))
      .exec(
        session => {
          var getJson = session.get("GetResponse").asOption[String];
          var runId = session.get("runId").asOption[String]
        //  println("Run ID === ")
        //  println(runId.get)
          idFeeder(runId.get)
          session
        }
      )
  }

  object GetRunIdDetails{

    println("Length=" + idList.length)
    val getRunIdDetails = repeat(idList.length) {

      exec(http("Getting Run Details")
        .get(s"****/***" + getRunId())
        .check(status in (200 to 209))
        .check(bodyString.saveAs("GetRunIdResponse"))
      )
        .exec(
          session => {
            var getResponse = session.get("GetRunIdResponse").asOption[String];
            println("Response from Get" + getResponse.get)
            session
          }
        )

    }
  }

  val scn = scenario("All run details")
    .exec(GetAllRunDetails.getAllRunDetails, GetRunIdDetails.getRunIdDetails)

  setUp(scn.inject(atOnceUsers(1)));

}

But here why is GetAllRunDetails.getAllRunDetails not running before GetRunIdDetails.getRunIdDetails? That is my idList is never getting defined.

The error that I am getting is this:

Length=0
0
Exception in thread "main" java.lang.IndexOutOfBoundsException: 0
    at scala.collection.LinearSeqOptimized$class.apply(LinearSeqOptimized.scala:65)
    at scala.collection.immutable.List.apply(List.scala:84)
    at nike.runwithme.performance.RunWithMePerfTest.getRunId(RunWithMePerfTest.scala:27)
    at nike.runwithme.performance.RunWithMePerfTest$GetRunIdDetails$.<init>(RunWithMePerfTest.scala:57)
    at nike.runwithme.performance.RunWithMePerfTest.GetRunIdDetails$lzycompute(RunWithMePerfTest.scala:51)
    at nike.runwithme.performance.RunWithMePerfTest.GetRunIdDetails(RunWithMePerfTest.scala:51)
    at nike.runwithme.performance.RunWithMePerfTest.<init>(RunWithMePerfTest.scala:73)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at java.lang.Class.newInstance(Class.java:442)
    at io.gatling.app.Gatling$.io$gatling$app$Gatling$$$anonfun$1(Gatling.scala:41)
    at io.gatling.app.Gatling$lambda$1.apply(Gatling.scala:41)
    at io.gatling.app.Gatling$lambda$1.apply(Gatling.scala:41)
    at io.gatling.app.Gatling.run(Gatling.scala:92)
    at io.gatling.app.Gatling.runIfNecessary(Gatling.scala:75)
    at io.gatling.app.Gatling.start(Gatling.scala:65)
    at io.gatling.app.Gatling$.start(Gatling.scala:57)
    at io.gatling.app.Gatling$.fromArgs(Gatling.scala:49)
    at io.gatling.app.Gatling$.main(Gatling.scala:43)
    at io.gatling.app.Gatling.main(Gatling.scala)

Upvotes: 0

Views: 2092

Answers (2)

Pritam Banerjee
Pritam Banerjee

Reputation: 18923

So here is the answer that worked for me. Almost same code, but added a session to the second scenario. Makes sense, because everything is added to the session:

/**
  * Created by pbane3 on 11/10/16.
  *
  * The First test gets the Run Id's
  *
  * Then it creates a a List of all the RunIDs
  *
  * After that loops through each of the RunIDs
  * and makes a GET call for each of them
  */

import io.gatling.core.Predef._
import io.gatling.http.Predef._
import scala.concurrent.duration._
import scala.concurrent.forkjoin.ThreadLocalRandom
import scala.collection.mutable
import scala.collection.Map
import java.io.File
import java.io.PrintWriter



class RunWithMePerfTest extends Simulation {

  //this is used to store the list of the runIds
  var idList  = List[String]()

  var count = 0;

  //used to build the list and feed to the session
  def idFeeder(idString:String):Unit = {
    idList = idString.split(",").map(_.trim).toList;
    println(idList)
  }

  //used to access the list and feed to the session
  def getRunId() : String = {
     println(count)
     var id = idList(count);
     count = count+1;
     return id;
  }

  //makes the initial call to get all the run IDs
  object GetAllRunDetails {
    println("I come in scn1")
    val getAllRunDetails = exec(http("Get Run Ids")
      .get("https://someUrl")
      .check(status in (200 to 209))
      // .check(bodyString.saveAs("GetResponse"))
      .check(jsonPath("$..id").ofType[String].findAll.transform(_.mkString(",")).saveAs("runId")))
      .exec(
        session => {
          var getJson = session.get("GetResponse").asOption[String];
          var runId = session.get("runId").asOption[String]

          idFeeder(runId.get)
          session
        }
      )
  }

  //makes one get call for each of the run ids obtained from the last get call
  object GetRunIdDetails{
    val getRunIdDetails =  repeat(session=>idList.length) {
      exec(http("Getting Run Details")
        .get(session => (s"https://someUrl" + getRunId()))
        .check(status in (200 to 209))
        .check(bodyString.saveAs("GetRunIdResponse"))
      )
        .exec(
          session => {
            var getResponse = session.get("GetRunIdResponse").asOption[String];
            println("Response from Get:")
            println(getResponse.get)
            session
          }
        )
    }
  }

  val scn1 = scenario("All run details")
    .exec(GetAllRunDetails.getAllRunDetails)

  val scn2 = scenario("All run ID Details")
    .exec(GetRunIdDetails.getRunIdDetails)


  setUp(scn1.inject(atOnceUsers(1)),scn2.inject(nothingFor(10 seconds),atOnceUsers(1)));

}

Upvotes: 1

niharika_neo
niharika_neo

Reputation: 8531

You can chain your scenarios to run sequentially. Try creating two scenarios and then chain them eg.

scn1 = scenario("Get All run details")
    .exec(GetAllRunDetails.getAllRunDetails)

scn2 = scenario("bla").exec(GetRunIdDetails.getRunIdDetails)

seqScenario = scn1.exec(scn2)

Adding to the answer: exec gets initialized before your run. At that time since you are calling the .get(s"****/***" + getRunId()) method, there'e no data in idList yet, and so your run fails even before it starts. You can add another exec which puts the data in session before you can use it in your get call.

Upvotes: 0

Related Questions