1

I'm trying to write a load test for service. I want to build DeliveryObjects and publish them, each delivery must have a unique id. The problem I encounter is that I cant pass variables from the session to a function that I wrote (I know the documentation says I can't), also I can't "catch" the value on run time as I saw in several examples. So this is one thing I have tried:


object AdminClient extends FireClient {

  def getDeliveryStateByDeliveryId(name: String = "Get delivery state by ID",
                                   @Nullable deliveryId: Expression[String] = "${delivery_uuid}")
                                    : HttpClientRequest = {

// The deliveryId resolve to something like this: io.gatling.core.session.el.ElCompiler$$$Lambda$372/1144897090@473b3b7a
    println("delivery id in adminclient is: " + deliveryId)
    get(name)
      .uri(s"/url/${deliveryId}")
      .requestModeAdmin
      .allowOkStatus
  }
}

and the scenario looks like this (to make things simpler):


object LoadTest extends FireScenarios {

  val csvFeeder = csv("deliveries.csv")

  fireScenario("Load test starts")(_
    .feed(csvFeeder)
 .exec { session =>
      // Here delivery_uuid get a real value something like "b6070d6b-ce10-5fd3-b81d-ed356665f0e1"
      println("delivery id id:" + session.get("delivery_uuid").as[String])
      session
    }
    .exec(AdminClient.getDeliveryStateByDeliveryId())
  )
}

So I guess my question is how can I pass a value to the var "${delivery_uuid}" in the "getDeliveryStateByDeliveryId" method?

Note that I also can't just call the getDeliveryStateByDeliveryId method from withing the

exec{ session =>
AdminClient.getDeliveryStateByDeliveryId(deliveryId = session.get("delivery_uuid"))
session
}

Although the method gets the variable as I want, the Gatling throws an error that no request was sent and no report will be produced.

I'm very confused after reading the docs too many times, any help will be much appreciated.

1 Answers1

1

Let's sum up what you can find in the official documentation:

Expression[String] is a Scala type alias for (making it simple) scala.Function[Session, String]. Similarly, in Gatling's Java DSL, you directly pass java.util.Function<Session, String>.

Gatling's Scala DSL has some implicit conversion that transform String values passed to methods expecting a Function parameter into a proper function.

So if we make explicit what you've written, you actually have (doesn't compile, but you'll get the idea):

  def getDeliveryStateByDeliveryId(name: String = "Get delivery state by ID",
                                   @Nullable deliveryId: Expression[String] = session => session("delivery_uuid").as[String])
                                    : HttpClientRequest = {
    println("delivery id in adminclient is: " + deliveryId)
    get(name)
      .uri("/url/" + deliveryId)
      .requestModeAdmin
      .allowOkStatus
  }

This cannot possibly work. You're concatenating a String and a Function which, like in Java uses the toString inherited from Object.

Now, as you're a beginner, why do you need deliveryId to be a function? Can't it just be a String with the name of the desired attribute?

  def getDeliveryStateByDeliveryId(name: String = "Get delivery state by ID",
                                   deliveryId: String = "delivery_uuid")
                                    : HttpClientRequest =
    get(name)
      .uri(s"/url/#{$deliveryId}")
      .requestModeAdmin
      .allowOkStatus

object LoadTest extends FireScenarios {

  val csvFeeder = csv("deliveries.csv")

  fireScenario("Load test starts")(_
    .feed(csvFeeder)
    .exec(AdminClient.getDeliveryStateByDeliveryId())
  )
}
Stéphane LANDELLE
  • 6,076
  • 2
  • 10
  • 12
  • I've used this pattern before - passing session variable names - but have wondered if there are alternative approaches. Once scenarios get long I really want to break them apart like this and have more defined interfaces for them to enable composability, which this does, but it grates that you have to pass the variable name instead of the value. Kind of unavoidable, I guess? – James Warr Jun 30 '22 at 04:02
  • Thanks for the comment. What I need is to get "deliveryId" from a feeder file dynamically, so I can repeat that for many users. for that (if I got it right), I need "delivery_uuid" to be a function that will be translated to a String. I expect to transfer data from ".feed(csvFeeder)" to the seesion, and from the session to "getDeliveryStateByDeliveryId()" – Meni Toledano Jun 30 '22 at 07:47
  • Honestly, you really don't need your `deliveryId` parameter. You could just ditch it and simply write `.uri("/url/#{delivery_uuid}")`. – Stéphane LANDELLE Jun 30 '22 at 10:07
  • It doesnt work, what worked for me was:``` .uri(s"/url/") .append(deliveryId)``` so likestephan explained the "toString" method wont get call and the gatling function can handle the "Expresion" var. – Meni Toledano Jun 30 '22 at 14:46