Scenario

This is the reference of the different components available to write scenarios with Gatling.

Bootstrapping

scenario is the way to bootstrap a new scenario.

scenario("My Scenario")

You can use any character in the name of the scenario except tabulations: t.

Structure elements

Exec

The exec method is used to execute an action. Actions are usually requests (HTTP, LDAP, POP, IMAP, etc) that will be sent during the simulation. Any action that will be executed will be called with exec.

For example, when using the Gatling HTTP module you would write the following line:

scenario("My Scenario")
  .exec(http("Get Homepage").get("http://github.com/gatling/gatling"))

exec can also be passed an Expression function.

This can be used for manually debugging or editing the Session, e.g.:

exec { session =>
  // displays the content of the session in the console (debugging only)
  println(session)

  // return the original session
  session
}

exec { session =>
  // return a new session instance with a new "foo" attribute whose value is "bar"
  session.set("foo", "bar")
}

Note

For those who wonder how the plumbing works and how you can return a Session instead of Validation[Session] in the above examples, that’s thanks to an implicit conversion.

Warning

Gatling DSL components are immutable ActionBuilder(s) that have to be chained altogether and are only built once on startup. The results is a workflow chain of Action(s). These builders don’t do anything by themselves, they don’t trigger any side effect, they are just definitions. As a result, creating such DSL components at runtime in functions is completely meaningless. If you want conditional paths in your execution flow, use the proper DSL components (doIf, randomSwitch, etc)

exec { session =>

  if (someSessionBasedCondition(session)) {
    // just create a builder that is immediately discarded, hence doesn't do anything
    // you should be using a doIf here
    http("Get Homepage").get("http://github.com/gatling/gatling")
  }
  session
}

flattenMapIntoAttributes is a built-in Session Expression as mentioned above.

It exposes the content of a Map into attributes, e.g.:

// assuming the Session contains an attribute named "theMap" whose content is :
// Map("foo" -> "bar", "baz" -> "qix")

exec(flattenMapIntoAttributes("${theMap}"))

// the Session contains 2 new attributes "foo" and "baz".

Pause

pause

When a user sees a page he/she often reads what is shown and then chooses to click on another link. To reproduce this behavior, the pause method is used.

There are several ways of using it:

  • Fixed pause duration:
    • pause(duration: Duration)
    • pause(duration: String, unit: TimeUnit = TimeUnit.SECONDS)
    • pause(duration: Expression[Duration])
  • Uniform random pause duration:
    • pause(min: Duration, max: Duration)
    • pause(min: String, max: String, unit: TimeUnit)
    • pause(min: Expression[Duration], max: Expression[Duration])

Note

All those methods also have an optional force parameter that overrides the pause type defined in the set up. Possible values are the same ones than for global definition.

pace

If you want to control how frequently an action is executed, to target iterations per hour type volumes. Gatling support a dedicated type of pause: pace, which adjusts its wait time depending on how long the chained action took. E.g.:

forever(
  pace(5 seconds)
    .exec(
      pause(1 second, 4 seconds) // Will be run every 5 seconds, irrespective of what pause time is used
    )
)

There are several ways of using it:

  • Fixed pause duration:
    • pace(duration: Duration)
    • pace(duration: String, unit: TimeUnit = TimeUnit.SECONDS)
    • pace(duration: Expression[Duration])
  • Uniform random pause duration:
    • pace(min: Duration, max: Duration)
    • pace(min: String, max: String, unit: TimeUnit)
    • pace(min: Expression[Duration], max: Expression[Duration])

rendezVous

In some cases, you may want to run some requests, then pause users until all other users have reached a rendez-vous point. For this purpose Gatling has the rendezVous(users: Int) method which takes the number of users to wait.

Loop statements

repeat

repeat(times, counterName) {
  myChain
}

times can be an Int, an EL string pointing to an Int Session attribute, or an Expression[Int].

counterName is optional and can be used to force the name of the loop counter. Current value can be retrieved on the Session as an attribute with a counterName name.

repeat(20) {myChain}     // will loop on myChain 20 times
repeat("${myKey}") {myChain}    // will loop on myChain (Int value of the Session attribute myKey) times
repeat(session => session("foo").as[Int] /* or anything that returns an Int*/) {myChain}

Warning

Don’t forget that the counter starts at 0!

foreach

foreach(sequenceName, elementName, counterName) {
  myChain
}

sequenceName can be a sequence, an EL string pointing to a Seq[Any] Session attribute, or an Expression[Seq[Any]]

elementName is a the name of the Session attribute that will hold the current element.

counterName is optional.

during

during(duration, counterName, exitASAP) {
  myChain
}

duration can be an Int for a duration in seconds, or a duration expressed like 500 milliseconds.

counterName is optional.

exitASAP is optional and defaults to true. If true, the condition will be evaluated for each element inside the loop, possibly causing to exit before reaching the end of the iteration.

asLongAs

asLongAs(condition, counterName, exitASAP) {
  myChain
}

condition is a session function that returns a boolean.

counterName is optional.

exitASAP is optional and defaults to false. If true, the condition will be evaluated for each element inside the loop, possibly causing to exit before reaching the end of the iteration.

forever

forever(counterName) {
  myChain
}

counterName is optional.

Conditional statements

doIf

Gatling’s DSL has conditional execution support. If you want to execute a specific chain of actions only when some condition is satisfied, you can do so using the doIf method.

doIf("${myBoolean}") {
  // executed if the session value stored in "myBoolean" is true
  exec(http("...").get("..."))
}

If you want to test complex conditions, you’ll have to pass an Expression[Boolean]:

doIf(session => session("myKey").as[String].startsWith("admin")) {
  // executed if the session value stored in "myKey" starts with "admin"
  exec(http("if true").get("..."))
}

doIfEquals

Îf your test condition is simply to compare two values, you can simply use doIfEquals:

doIfEquals("${actualValue}", "expectedValue") {
  // executed if the session value stored in "actualValue" is equal to "expectedValue"
  exec(http("...").get("..."))
}

doIfOrElse

Similar to doIf, but with a fallback if the condition evaluates to false.

doIfOrElse(session => session("myKey").as[String].startsWith("admin")) {
  // executed if the session value stored in "myKey" starts with "admin"
  exec(http("if true").get("..."))
} {
  // executed if the session value stored in "myKey" does not start with "admin"
  exec(http("if false").get("..."))
}

Warning

doIfOrElse only takes an Expression[Boolean], not the key/value signature.

doIfEqualsOrElse

Similar to doIfEquals but with a fallback if the condition evaluates to false.

doIfEqualsOrElse(session => session("actualValue").as[String], "expectedValue") {
  // executed if the session value stored in "actualValue" equals to "expectedValue"
  exec(http("if true").get("..."))
} {
  // executed if the session value stored in "actualValue" is not equal to "expectedValue"
  exec(http("if false").get("..."))
}

doSwitch

Add a switch in the chain. Every possible sub-chain is defined with a key. Switch is selected through the matching of a key with the evaluation of the passed expression. If no switch is selected, the switch is bypassed.

doSwitch("${myKey}") ( // beware: use parentheses, not curly braces!
  key1 -> chain1,
  key1-> chain2
)

doSwitchOrElse

Similar to doSwitch, but with a fallback if no switch is selected.

doSwitchOrElse("${myKey}") ( // beware: use parentheses, not curly braces!
  key1 -> chain1,
  key1-> chain2
) (
  myFallbackChain
)

randomSwitch

randomSwitch can be used to emulate simple Markov chains. Simple means cyclic graphs are not currently supported.

randomSwitch( // beware: use parentheses, not curly braces!
  percentage1 -> chain1,
  percentage2 -> chain2
)

Percentages sum can’t exceed 100%. If sum is less than 100%, users that won’t fall into one of the chains will simply exit the switch and continue. Once users are done with the switch, they simply continue with the rest of the scenario.

Note

Percentages should be format as following: 50% -> 50, 33.3% -> 33.3 and so on.

randomSwitchOrElse

Similar to randomSwitch, but with a fallback if no switch is selected (i.e.: random number exceeds percentages sum).

randomSwitchOrElse( // beware: use parentheses, not curly braces!
  percentage1 -> chain1,
  percentage2 -> chain2
) {
  myFallbackChain
}

uniformRandomSwitch

Similar to randomSwitch, but with an uniform distribution amongst chains.

uniformRandomSwitch( // beware: use parentheses, not curly braces!
  chain1,
  chain2
)

roundRobinSwitch

Similar to randomSwitch, but dispatch uses a round-robin strategy.

roundRobinSwitch( // beware: use parentheses, not curly braces!
  chain1,
  chain2
)

Error management

tryMax

tryMax(times, counterName) {
  myChain
}

myChain is expected to succeed as a whole. If an error happens (a technical exception such as a timeout, or a failed check), the user will bypass the rest of the chain and start over from the beginning.

times is the maximum number of attempts.

counterName is optional.

exitBlockOnFail

exitBlockOnFail {
  myChain
}

Quite similar to tryMax, but without looping on failure.

exitHereIfFailed

exitHereIfFailed

Make the user exit the scenario from this point if it previously had an error.

Groups definition

group(groupName) {
  myChain
}

Create group of requests to model process or requests in a same page. Groups can be nested. Beware that group names mustn’t contain commas.

Protocol definition

You can configure protocols at scenario level with protocols method:

scn.inject(atOnceUsers(5)).protocols(httpConf)

See the dedicated section for http protocol definition here.

Pause definition

You can configure pause definition at scenario level, see here for more information.

Throttling

You can also configure throttling at scenario level with throttle method.

This way, you can configure different throttling profiles for different scenarios running in the same simulation.

scn.inject(rampUsers(500) over (10 minutes)).throttle(reachRps(100) in (10 seconds), holdFor(10 minutes))

For further information see the dedicated section here.