Using .andThen in the simulation

Hi All,

I am trying to include scripts into my suite of tests that will use .andThen with a parent and child script. The parent script creates all the dependancies such as users and tenants and the child will create the assets which will belong to the tenants and users. My framework has the code, scenarios and simulations separated out. I am not sure how to integrate andThen into my scripts.

Scenario.scala :
package msx.performance.com.api.manageddevice.scenario

import io.gatling.core.Predef._
import io.gatling.core.structure.{ChainBuilder, ScenarioBuilder}
import msx.performance.com.api.consume.request.MSXPlatformConsume
import msx.performance.com.config._
import msx.performance.com.api.manageddevice.request._
import msx.performance.com.api.idm.request._

object Scenario extends BaseSimulation {

def createScenario(name: String, chains: ChainBuilder*): ScenarioBuilder = {
scenario(name)
.exec(chains)
.pause(Constants.pause)
.exec { session =>
println(session(“deviceId”).as[String])
session
}
}

val scnCreateNewTenantSite: ScenarioBuilder = createScenario(
“SCN_MSX_CREATE_TENANT_SITE”,
MSXPlatformLogin.getTokenFromAuthorize,
MSXPlatformLogin.getIsTokenValid,
MSXPlatformTenant.createNewTenant
)

val scnCreateDeviceSite: ScenarioBuilder = createScenario(
“SCN_MSX_CREATE_DEVICE_SITE”,
MSXPlatformLogin.getTokenFromAuthorize,
MSXPlatformLogin.getIsTokenValid,
MSXPlatformManagedDeviceSites.findSite,
MSXPlatformManagedDeviceSites.addDevice,
MSXPlatformManagedDeviceSites.addDeviceToSite
)
}

Simulation.scala :

package msx.performance.com.api.manageddevice.simulation

import io.gatling.http.Predef._
import io.gatling.core.Predef.{nothingFor, }
import msx.performance.com.api.manageddevice.scenario.Scenario
import msx.performance.com.config.

import scala.concurrent.duration.DurationInt

class Simulation extends BaseSimulation {

val httpScenarios = Map (
“setUpTestEnvironment” → List(
Scenario.scnCreateNewTenantSite.inject(atOnceUsers(1))
),
“createDevicesAttachtoSite” → List(
Scenario.scnCreateDeviceSite.inject(nothingFor(5 seconds), rampUsers(Constants.userCount) during(Constants.rampDuration seconds))
)
)

setUp(httpScenarios(Constants.testScenarios):_*)
.protocols(httpConf)
.maxDuration(Constants.testDuration seconds)
.assertions(global.responseTime.percentile4.lte(Constants.responseTimeLTE),
global.successfulRequests.percent.gte(Constants.successRateGTE))

}

The above works great with concurrent scripts running, but I need to write it in a way where setUpTestEnvironment runs once and then createDevicesAttachtoSite runs several times after first script finishes. Any help will be great!!

-GK

I guess you visited Sequential Scenarios in our documentation?

I’m sorry, I cannot manage to read your code.
I stopped when I saw that:

object Scenario extends BaseSimulation

A Scenario IS NOT a Simulation.
To shorten our documentation, a Simulation often declares its own scenario, but never we mixed the concept of Scenario and Simulation (if that is really the case, please point it to us, it is a terrible mistake).

I often use the allegory with the theater play.

Gatling term | Theater term | Comment |

  • | - | - |
    Virtual User | Actor/Actress | A virtual user will simulate what a real user will do in such situations |
    Scenario | Script | What an actor/actress will say, where (s)he will be placed, etc. |
    Simulation | A play | When each actor will enter on stage, how many actors, etc. |

In this allegory, I assume you want to have (at least) 2 scenes.
andThen will be a perfect use, here.

But andThen is a keyword to use in the setUp of a Simulation to coordinates the different scenarios in play.

I hope that helps you!

Cheers!

Hi, No need to talk down to me, I reached out for help man. Honestly, I Don’t know what you are talking about. First of all I obviously omitted the api scripts and my base class (baseSimulation) - where I have my login, and all my repeatable code which extends gatling’s simulation library. Thanks for telling me how performance automation works :frowning:

I want to take my scenario.scala (the order and step by step instructions of my test scripts which I’ve separated into a test environment setup scenario and an asset creation scenario) and run them in an “andThen” Simulation (test setup first and then asset creation second). I am only asking about the syntax based on how I have used chain builder and scenario builder. If you don’t want to help just say you don’t want to help.

Personally, I don’t understand why you feel “talked down to”. Maybe not being a native english speaker.

First, Sébastien pointed out that you’re misusing the term “Scenario”. In Gatling’s terminology, a Scenario is not a Simulation so “object Scenario extends BaseSimulation” is wrong. At best, it makes things confusing for people using the proper terminology. Worse, it can cause some class name clashes with https://github.com/gatling/gatling/blob/main/gatling-core/src/main/scala/io/gatling/core/scenario/Scenario.scala.

Then, Sébastien provided you with a pointer to the “andThen” documentation: https://gatling.io/docs/current/general/simulation_setup/#sequential-scenarios
Could you please elaborate on what you don’t understand?

Gatling’s terminology: https://gatling.io/docs/current/general/concepts/

OK, sorry, I named my base class in an ugly way, I will fix so that SB can read my code without giving him a fluttering heart beat…I know what scenario and simulation mean…That was not anywhere close to my question. I need to figure out the syntax for .andThen. I used your documentation just now but I get a type mismatch error. If you can help with that it would be more helpful too me…Again if you don’t want to help with “andThen” just say so. I’m sorry to seem so ungrateful but for some reason you are focusing in on something that is neither here nor there and has been working in my scripts for 2+ years now.

setUp(
  Scenario.scnCreateNewTenantSite.inject(atOnceUsers(1))
    .andThen( Scenario.scnCreateDeviceSite.inject(rampUsers(Constants.userCount).during(Constants.rampDuration seconds)))
 ).assertions(global.responseTime.percentile4.lte(Constants.responseTimeLTE),
    global.successfulRequests.percent.gte(Constants.successRateGTE))

10:22:08.465 [main][ERROR][ZincCompiler.scala:153] i.g.c.ZincCompiler$ - /Users/gkandale/gatling/msx4.0/us33569-manageddevice-scale-scripts/msx-performance-tools/src/test/scala/msx/performance/com/api/manageddevice/simulation/Simulation.scala:38:54: type mismatch;
found : io.gatling.core.structure.PopulationBuilder
required: io.gatling.commons.validation.Validation[io.gatling.core.structure.PopulationBuilder] => ?
.andThen( Scenario.scnCreateDeviceSite.inject(rampUsers(Constants.userCount).during(Constants.rampDuration seconds)))
^
10:22:08.501 [main][ERROR][ZincCompiler.scala:124] i.g.c.ZincCompiler$ - one error found
10:22:08.505 [main][ERROR][ZincCompiler.scala:220] i.g.c.ZincCompiler$ - Compilation crashed
sbt.internal.inc.CompileFailed: null
at sbt.internal.inc.AnalyzingCompiler.call(AnalyzingCompiler.scala:253)
at sbt.internal.inc.AnalyzingCompiler.compile(AnalyzingCompiler.scala:122)
at sbt.internal.inc.AnalyzingCompiler.compile(AnalyzingCompiler.scala:95)
at sbt.internal.inc.MixedAnalyzingCompiler.$anonfun$compile$4(MixedAnalyzingCompiler.scala:91)
at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.java:23)
at sbt.internal.inc.MixedAnalyzingCompiler.timed(MixedAnalyzingCompiler.scala:186)
at sbt.internal.inc.MixedAnalyzingCompiler.$anonfun$compile$3(MixedAnalyzingCompiler.scala:82)
at sbt.internal.inc.MixedAnalyzingCompiler.$anonfun$compile$3$adapted(MixedAnalyzingCompiler.scala:77)
at sbt.internal.inc.JarUtils$.withPreviousJar(JarUtils.scala:215)
at sbt.internal.inc.MixedAnalyzingCompiler.compileScala$1(MixedAnalyzingCompiler.scala:77)
at sbt.internal.inc.MixedAnalyzingCompiler.compile(MixedAnalyzingCompiler.scala:146)
at sbt.internal.inc.IncrementalCompilerImpl.$anonfun$compileInternal$1(IncrementalCompilerImpl.scala:343)
at sbt.internal.inc.IncrementalCompilerImpl.$anonfun$compileInternal$1$adapted(IncrementalCompilerImpl.scala:343)
at sbt.internal.inc.Incremental$.doCompile(Incremental.scala:120)
at sbt.internal.inc.Incremental$.$anonfun$compile$4(Incremental.scala:100)
at sbt.internal.inc.IncrementalCommon.recompileClasses(IncrementalCommon.scala:180)
at sbt.internal.inc.IncrementalCommon.cycle(IncrementalCommon.scala:98)
at sbt.internal.inc.Incremental$.$anonfun$compile$3(Incremental.scala:102)
at sbt.internal.inc.Incremental$.manageClassfiles(Incremental.scala:155)
at sbt.internal.inc.Incremental$.compile(Incremental.scala:92)
at sbt.internal.inc.IncrementalCompile$.apply(Compile.scala:75)
at sbt.internal.inc.IncrementalCompilerImpl.compileInternal(IncrementalCompilerImpl.scala:348)
at sbt.internal.inc.IncrementalCompilerImpl.$anonfun$compileIncrementally$1(IncrementalCompilerImpl.scala:301)
at sbt.internal.inc.IncrementalCompilerImpl.handleCompilationError(IncrementalCompilerImpl.scala:168)
at sbt.internal.inc.IncrementalCompilerImpl.compileIncrementally(IncrementalCompilerImpl.scala:248)
at sbt.internal.inc.IncrementalCompilerImpl.compile(IncrementalCompilerImpl.scala:74)
at io.gatling.compiler.ZincCompiler$.doCompile(ZincCompiler.scala:211)
at io.gatling.compiler.ZincCompiler$.delayedEndpoint$io$gatling$compiler$ZincCompiler$1(ZincCompiler.scala:216)
at io.gatling.compiler.ZincCompiler$delayedInit$body.apply(ZincCompiler.scala:39)
at scala.Function0.apply$mcV$sp(Function0.scala:39)
at scala.Function0.apply$mcV$sp$(Function0.scala:39)
at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:17)
at scala.App.$anonfun$main$1$adapted(App.scala:80)
at scala.collection.immutable.List.foreach(List.scala:392)
at scala.App.main(App.scala:80)
at scala.App.main$(App.scala:78)
at io.gatling.compiler.ZincCompiler$.main(ZincCompiler.scala:39)
at io.gatling.compiler.ZincCompiler.main(ZincCompiler.scala)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at io.gatling.mojo.MainWithArgsInFile.runMain(MainWithArgsInFile.java:50)
at io.gatling.mojo.MainWithArgsInFile.main(MainWithArgsInFile.java:33)

I see a type mismatch error in the stack trace you printed. Please check that.
I dont see any issues with the usage of andThen.
Also you may have to check the gatling version > 3.4.0

Yes, compiles on my side too, so I agree, it’s likely you’re using an outdated version of Gatling from before the “andThen” feature was introduced.
https://gatling.io/docs/current/whats_new/3.4/

Thank you Sri and Stéphane. I appreciate your straight forward responses. I will check version.

Thank you!
GK

As you suspected, it was the version number, so that is all set now, thank you very much. One last question, are the session variables created in the the parent scenario available to the child scenarios too when using .andThen? Or are they gone once the parent scenario finishes?

-GK

Those are different scenarios with distinct injection profiles, hence distinct virtual users.
So nothing shared unless you implement something yourself.

George,
This is what we did for our performance tests.

  1. Created a parent CSV feeder
  2. Set the data in the feeder in the session object.
  3. Used the session object to feed the data in the request for the api. Before that do a check doIf(session => Option(“request_data”).forall(session(_).asOption[String].nonEmpty))
  4. Used injection profile to run the tests

Thank you Sri! I appreciate your response. Will give that a go. I’ll let you know how it goes.

-GK

Also, kind reminder of the requirements on this group: https://groups.google.com/g/gatling

  • Make sure you’re using an up-to-date Gatling version