0

I have two scenarios in my script. 1st "getAssets" scenario will fetch all asset IDs and save it in a list, 2nd scenario "fetchMetadata" will iterate those IDs.

I have to exeecute "getAssets" scenario only once to fetch all the IDs, and then "fetchMetadata" scenario will execute till given time duration.

Here is the Json response of "/api/assets;limit=$limit" request (We are fetching id from here using $.assets[*].id),

{
  "assets": [
    {
      "id": 3010411,
      "name": "Asset 2016-11-22 20:06:07",
      ....
      ....
    },
    {
      "id": 3010231,
      "name": "Asset 2016-11-22 20:07:07",
      ....
      ....
    }, and so on..

Here is the code

import java.util.concurrent.ThreadLocalRandom
import scala.concurrent.duration._
import io.gatling.core.Predef._
import io.gatling.http.Predef._

class getAssetsMetadata extends Simulation {
    val getAssetURL = System.getProperty("getAssetURL", "https://performancetesting.net")
    val username = System.getProperty("username", "performanceuser")
    val password = System.getProperty("password", "performanceuser")
    val limit = Integer.getInteger("limit", 1000).toInt
    val userCount = Integer.getInteger("userCount", 100).toInt
    val duration = Integer.getInteger("duration",1).toInt //in minutes

    var IdList: Seq[String] = _   

    val httpProtocol = http
        .basicAuth(username, password)
        .baseURL(getAssetURL)
        .contentTypeHeader("""application/vnd.v1+json""")

    // Scenario 1 get assets
    val getAssets = scenario("Get Assets")
            .exec(http("List of Assets")
            .get(s"""/api/assets;limit=$limit""")
            .check(jsonPath("$.assets[*].id").findAll.transform {v => IdList = v; v }.saveAs("IdList"))
            )

    // Scenario 2 Fetch Metadata
    val fetchMetadata = scenario("Fetch Metadata")
        .exec(_.set("IdList", IdList))
        .exec(http("Metadata Request")
            .get("""/api/assets/${IdList.random()}/metadata""")
            )

    val scn = List(getAssets.inject(atOnceUsers(1)), fetchMetadata.inject(constantUsersPerSec(userCount) during(duration minutes)))
    setUp(scn).protocols(httpProtocol) 
}   

:::ERROR:::

It throws "Value is null" (While we have 10 million asset IDs here). here is the Gatling log

14883 [GatlingSystem-akka.actor.default-dispatcher-4] INFO  io.gatling.http.config.HttpProtocol - Warm up done
14907 [GatlingSystem-akka.actor.default-dispatcher-4] INFO  io.gatling.http.config.HttpProtocol - Start warm up
14909 [GatlingSystem-akka.actor.default-dispatcher-4] INFO  io.gatling.http.config.HttpProtocol - Warm up done
14911 [GatlingSystem-akka.actor.default-dispatcher-4] INFO  i.g.core.controller.Controller - Total number of users : 6001
14918 [GatlingSystem-akka.actor.default-dispatcher-6] INFO  i.g.c.r.writer.ConsoleDataWriter - Initializing
14918 [GatlingSystem-akka.actor.default-dispatcher-3] INFO  i.g.c.result.writer.FileDataWriter - Initializing
14923 [GatlingSystem-akka.actor.default-dispatcher-6] INFO  i.g.c.r.writer.ConsoleDataWriter - Initialized
14928 [GatlingSystem-akka.actor.default-dispatcher-3] INFO  i.g.c.result.writer.FileDataWriter - Initialized
14931 [GatlingSystem-akka.actor.default-dispatcher-4] DEBUG i.g.core.controller.Controller - Launching All Scenarios
14947 [GatlingSystem-akka.actor.default-dispatcher-12] ERROR i.g.http.action.HttpRequestAction - 'httpRequest-2' failed to execute: Value is null
14954 [GatlingSystem-akka.actor.default-dispatcher-4] DEBUG i.g.core.controller.Controller - Finished Launching scenarios executions
14961 [GatlingSystem-akka.actor.default-dispatcher-4] DEBUG i.g.core.controller.Controller - Setting up max duration
14962 [GatlingSystem-akka.actor.default-dispatcher-4] INFO  i.g.core.controller.Controller - Start user #7187317726850756780-0
14963 [GatlingSystem-akka.actor.default-dispatcher-4] INFO  i.g.core.controller.Controller - Start user #7187317726850756780-1
14967 [GatlingSystem-akka.actor.default-dispatcher-4] INFO  i.g.core.controller.Controller - End user #7187317726850756780-1
14970 [GatlingSystem-akka.actor.default-dispatcher-4] INFO  i.g.core.controller.Controller - Start user #7187317726850756780-2
14970 [GatlingSystem-akka.actor.default-dispatcher-5] INFO  io.gatling.http.ahc.HttpEngine - Sending request=List of Assets uri=https://performancetesting.net/api/assets;limit=1000: scenario=Get Assets, userId=7187317726850756780-0
14970 [GatlingSystem-akka.actor.default-dispatcher-7] ERROR i.g.http.action.HttpRequestAction - 'httpRequest-2' failed to execute: Value is null
14972 [GatlingSystem-akka.actor.default-dispatcher-7] INFO  i.g.core.controller.Controller - End user #7187317726850756780-2
14980 [GatlingSystem-akka.actor.default-dispatcher-7] ERROR i.g.http.action.HttpRequestAction - 'httpRequest-2' failed to execute: Value is null
14980 [GatlingSystem-akka.actor.default-dispatcher-4] INFO  i.g.core.controller.Controller - Start user #7187317726850756780-3
14984 [GatlingSystem-akka.actor.default-dispatcher-4] INFO  i.g.core.controller.Controller - End user #7187317726850756780-3
.....
.....
.....
61211 [GatlingSystem-akka.actor.default-dispatcher-12] INFO  i.g.core.controller.Controller - Start user #7187317726850756780-4626
61211 [GatlingSystem-akka.actor.default-dispatcher-7] ERROR i.g.http.action.HttpRequestAction - 'httpRequest-2' failed to execute: Value is null
61211 [GatlingSystem-akka.actor.default-dispatcher-7] INFO  i.g.core.controller.Controller - End user #7187317726850756780-4626
61224 [GatlingSystem-akka.actor.default-dispatcher-2] INFO  i.g.core.controller.Controller - Start user #7187317726850756780-4627
61225 [GatlingSystem-akka.actor.default-dispatcher-5] INFO  io.gatling.http.ahc.HttpEngine - Sending request=Metadata Request uri=https://performancetesting.net/api/assets/3010320/metadata: scenario=Fetch Metadata, userId=7187317726850756780-4627
61230 [GatlingSystem-akka.actor.default-dispatcher-12] INFO  i.g.core.controller.Controller - Start user #7187317726850756780-4628
61230 [GatlingSystem-akka.actor.default-dispatcher-7] INFO  io.gatling.http.ahc.HttpEngine - Sending request=Metadata Request uri=https://performancetesting.net/api/assets/3009939/metadata: scenario=Fetch Metadata, userId=7187317726850756780-4628
61233 [GatlingSystem-akka.actor.default-dispatcher-2] INFO  i.g.core.controller.Controller - End user #7187317726850756780-0
61233 [New I/O worker #12] DEBUG c.n.h.c.p.netty.handler.Processor - Channel Closed: [id: 0x8c94a1ae, /192.168.100.108:56739 :> performancetesting.net/10.20.14.176:443] with attribute INSTANCE

---- Requests ------------------------------------------------------------------
> Global                                                   (OK=261    KO=40    )
> Metadata Request                                         (OK=260    KO=40    )
> List of Assets                                           (OK=1      KO=0     )
---- Errors --------------------------------------------------------------------
> Value is null                                                      40 (100.0%)
================================================================================

Thank you.

Peter
  • 855
  • 2
  • 15
  • 35

1 Answers1

1

The list of ID is not passed to the other scenario, because it is obtained by another "user" (session).

Your simulation reads like the following

  • 1 user is obtaining the list of IDs (and keeps the list for itself)
  • AT THE SAME TIME, n users try to fetch assets with an (undefined) list of IDs

The first user doesnt talk to the others, both scenario injections are independent of each other.

A way to solve this is to store the list in a shared container (i.e. AtomicReference) and access this container from the second scenario. To ensure, the container is populated, inject a nothingFor step at the beginning of the second scenario in order to wait for the first scenario to finish.

Another way is to fetch the list of IDs in the beginning of the second scenario - if it has not been fetched before (see container above).

I'm sure there are ways to accomplish this as well (i.e. using some feeder and fetch the list of ids before the actual test)

Gerald Mücke
  • 10,724
  • 2
  • 50
  • 67
  • I have tried with .pause() in 2nd scenario and it works. as till pause time 1st scenario fetches all the IDs and then 2nd scenario starts. But how can I implement if I want that my 2nd request will not start until 1st finishes? If possible please give example. Thanks Gerald. – Peter May 18 '17 at 08:55
  • as you have your simulation using "constantUsersPerSec" you could use a `doIf`statement and check on a condition set by the first scenario. The first arriving users may do nothing, but everyone else afterwards should run their sequence. – Gerald Mücke May 18 '17 at 09:00
  • val scn1 = scenario("scenario1") .exec(getAssets) val scn2 = scenario("scenario2") .exec(fetchMetadata) setUp(scn1.inject(atOnceUsers(1)), scn2.inject(constantUsersPerSec(userCount) during(duration minutes))).protocols(httpProtocol) I have tried with this but it didnt work. I want to execute this scenarios in chain. Could you help me here? – Peter May 19 '17 at 08:29