In this blog post, we’ll explore how to use loops and conditional statements in Gatling to improve the flow and flexibility of your performance testing scripts. The complete code can be found at the GitHub repo.
Why do Loops and Conditionals Matter in Load Testing?
●
Loops: In real-world scenarios, users interact with web applications
repetitively browsing through multiple pages, making repeated API calls,
or performing continuous actions within the application. Using loops in Gatling helps simulate such behavior.
●
Conditional Statements: Not all users behave the same way, and sometimes
you may want to perform different actions based on specific
conditions—such as whether a certain request was successful or based on
the user's profile or session data. Conditional logic allows you to
introduce this variability into your scripts.
Now, let's look at how to implement loops and conditional statements in
Gatling.
1. Loops in Gatling
a) repeat Loop
The repeat loop repeats a block of code a specific number of times. This is useful when you want to simulate repetitive user behavior, such as submitting forms or making API requests multiple times.
ScenarioBuilder repeat = scenario("Repeat loop")
.exec(repeat(5).on(exec(carsClient.getCarByBrand("tata"))));
Above code will repeat the call to getCar API 5 times.
Repeat loop takes 2 params:
1. times: number of times to repeat the loop
2. counterName: optional, key to the loop counter as stored in session
b) forEach Loop
forEach loop allows you to iterate
over a list and perform an operation on each element.
ScenarioBuilder forEach = scenario("For Each loop")
.exec(foreach(List.of("tata", "ford", "maruti"), "brand")
.on(carsClient.getCarByBrand("#{brand}")));
forEach loop takes 3 parameters:
-
the list of elements to iterate over
-
elementName: the key to the current element in the Session
-
counterName: optional, key to the loop counter as stored in session
Here getCarByBrand API will be executed three times with different query params each time tata, ford and maruti.
c) during Loop
The during
loop is used for iteration over a given duration of time. During loop
accepts three parameters:
-
duration
-
counterName: optional, key to the loop counter as stored in session
-
exitAsap: Optional, default is true
The last parameter, exitASAP, defaults to true, meaning the loop will terminate immediately once the specified duration is reached, even if there are remaining actions to complete the current iteration. This could be problematic if subsequent actions depend on the execution of all requests within the loop.
ScenarioBuilder during = scenario("During loop")
.exec(during(Duration.ofSeconds(2))
.on(exec(carsClient.getCarByBrand("tata"))));
In the above example during loop will exit as soon as 2 seconds are over.
ScenarioBuilder duringExitAsap = scenario("During loop exit asap")
.exec(during(Duration.ofSeconds(2), false)
.on(exec(carsClient.getCarByBrand("tata"))));
In the above example exitAsap is set to false which means that all the actions inside during loop will be executed even if the 2 seconds have passed.
d) asLongAs Loop
The asLongAs loop is used to execute a block of
actions repeatedly while a condition remains true, much like a while
loop in many programming languages. The condition is evaluated at the
start of each iteration.
asLongAs loop takes 3
parameters:
-
condition: boolean, gatling EL
resolving to boolean or a function
-
counterName: optional, key to the loop counter as stored
- exitAsap: Optional, default is true
ScenarioBuilder asLongAs = scenario("As long as loop")
.exec(carsClient.getCarById("1"))
.exec(session -> carsClient.setCondition(session))
.exec(asLongAs("#{condition}", "counter")
.on(exec(carsClient.getCarByBrand("tata")
.exec(session -> {
if (session.getInt("counter") == 5) {
return session.set("condition", false);
}
return session;
})
)));
- Executes a request to get a car by its ID (getCarById("1")).
-
Sets a condition in the session based on the car's brand using the
setCondition method.
-
Enters an asLongAs loop that continues as long as the condition session
variable is true.
-
Inside the loop, it executes a request to get a car by the brand
"tata".
-
Checks if the counter session variable equals 5, and if so, sets the
condition session variable to false, breaking the loop.
e) doWhile Loop
The doWhile loop is used to repeatedly execute
a set of actions at least once and continue executing them while a
specific condition remains true. Unlike a aslongas loop, a doWhile
loop always runs the actions at least once, even if the condition is false
initially, because the condition is checked after each iteration.
This loop is useful when you need to execute an action once and then
repeat it based on a condition being true after the action is
executed.
doWhile loop takes 2 parameters:
-
condition: boolean, gatling EL resolving to boolean or a function
-
counterName: optional, key to the loop counter as stored.
ScenarioBuilder doWhile = scenario("do while loop")
.exec(session -> session.set("condition", false))
.exec(doWhile("#{condition}", "counter")
.on(exec(carsClient.getCarByBrand("tata")
.exec(session -> {
if (session.getInt("counter") == 5) {
return session.set("condition", false);
}
return session;
})
)));
- Sets the condition session variable to true.
-
Enters a doWhile loop that continues as long as the condition session
variable is true.
-
Inside the loop, it executes a request to get a car by the brand
"tata".
-
Checks if the counter session variable equals 5, and if so, sets the
condition session variable to false, breaking the loop.
f) asLongAsDuring Loop
The asLongAsDuring loop is a combination of two
concepts: it allows you to repeatedly execute a block of actions while a
condition is true for a specified duration. This means that the loop
continues executing the actions as long as the condition holds true, but
it will stop after the defined duration, even if the condition hasn't been
falsified yet.
asLongAsDuring loop takes 4 parameters:
-
condition: boolean, gatling EL
resolving to boolean or a function
-
counterName: optional, key to the loop counter as stored
-
exitAsap: Optional, default is
true
- duration
ScenarioBuilder asLongAsDuring = scenario("as long as during")
.exec(session -> session.set("condition", true))
.exec(asLongAsDuring("#{condition}", 3)
.on(exec(carsClient.getCarByBrand("tata")
)));
- Sets the condition session variable to true.
-
Enters an asLongAsDuring loop that continues as long as the condition
session variable is true and for a maximum of 3 seconds.
-
Inside the loop, it executes a request to get a car by the brand
"tata".
-
If the condition session variable is set to false before 3 seconds, the
loop will exit early.
g) doWhileDuring Loop
The doWhileDuring loop is a combination of two concepts: it allows you to execute a set of actions at least once and continue executing those actions while a condition is true, but it also imposes a time duration limit. The loop will keep executing the actions as long as the condition is true and the total duration hasn't passed.
doWhileDuring loop takes 3 parameters:
-
condition: boolean, gatling EL resolving to boolean or a function
-
counterName: optional, key to the loop counter as stored
-
Duration
ScenarioBuilder doWhileDuring = scenario("do while during")
.exec(session -> session.set("condition", true))
.exec(doWhileDuring("#{condition}", 3)
.on(exec(carsClient.getCarByBrand("tata")
)));
h) forever Loop
The forever loop is used to repeatedly execute
a block of actions indefinitely (or until the test is stopped). It’s
useful when you want to repeat a set of actions without any predefined
condition for exit, effectively creating an infinite loop. This type of
loop is often used in load testing scenarios where you want to simulate
continuous traffic, such as persistent users who keep making requests
without stopping.
ScenarioBuilder forever = scenario("forever")
.exec(forever().on(exec(carsClient.getCarByBrand("tata")
)));
2. Conditional Statements
a) doIf
The doIf construct allows you to execute a block of actions conditionally. It’s essentially an if-statement for your load simulation, meaning you can specify an expression, and if that expression evaluates to true, the actions inside the doIf block are executed.
ScenarioBuilder doIf = scenario("do if condition")
.exec(session -> session.set("condition", false))
.exec(doIf("#{condition}")
.then(exec(carsClient.getCarById("1"))))
.exec(session -> session.set("condition", true))
.exec(doIf("#{condition}")
.then(exec(carsClient.getCarById("1"))));
It performs the following steps:
-
Sets the condition session variable to false.
-
Executes a doIf block that checks the condition session variable. Since
condition is false, the request to get a car by ID (getCarById("1")) is
not executed.
-
Sets the condition session variable to true.
-
Executes another doIf block that checks the condition session variable.
Since condition is true, the request to get a car by ID
(getCarById("1")) is executed.
b) doIfEquals
The doIfEquals construct is used to execute a block of actions only if a given session attribute equals a specific value. It's a convenient way to conditionally execute actions based on exact matches of session variables.
ScenarioBuilder doIfEquals = scenario("do if equals condition")
.exec(session -> session.set("brand", "tata"))
.exec(doIfEquals("#{brand}", "tata")
.then(exec(carsClient.getCarById("1"))))
.exec(doIfEquals("#{brand}", "ford")
.then(exec(carsClient.getCarById("1"))));
1. Sets the `brand` session variable to `"tata"`.
2. Executes a `doIfEquals` block that checks if the `brand` session
variable equals `"tata"`. If true, it executes a request to get a car by
ID (`getCarById("1")`).
3. Executes another `doIfEquals` block that checks if the `brand` session
variable equals `"ford"`. Since session variable is tata the doIfEquals
block will not execute.
c) doIfOrElse
The doIfElse is a control structure used to conditionally execute a block of code depending on a specified condition. It's a way to perform different actions in your Gatling simulations based on whether the condition evaluates to true or false.
ScenarioBuilder doIfOrElse = scenario("do if or else condition")
.exec(session -> session.set("condition", true))
.exec(doIfOrElse("#{condition}")
.then(exec(carsClient.getCarById("1")))
.orElse(exec(carsClient.getCarById("2"))));
-
Sets the condition session variable to true.
-
Executes a doIfOrElse block that checks the condition session
variable.
-
If condition is true, it executes a request to get a car by ID
(getCarById("1")).
- If condition is false, it executes a request to get a car by ID (getCarById("2")).
d) doIfEqualsOrElse
The doIfEqualsOrElse is a control structure that allows you to perform actions based on whether a value is equal to a specific value. If the value equals the specified one, it executes a certain block of code; otherwise, it executes a different block of code.
ScenarioBuilder doIfEqualsOrElse = scenario("do if equals or else condition")
.exec(session -> session.set("brand", "tata"))
.exec(doIfEqualsOrElse("#{brand}", "tata")
.then(exec(carsClient.getCarById("1")))
.orElse(exec(carsClient.getCarById("2"))));
e) doSwitch
doSwitch is a control structure that allows you to perform different actions based on a condition that is evaluated at runtime. This is useful when you want to dynamically select between multiple alternative actions or workflows in your test scenario.
ScenarioBuilder doSwitch = scenario("do switch condition")
.exec(session -> session.set("brand", "#{brand}"))
.exec(doSwitch("#{brand}").on(
onCase("tata").then(exec(carsClient.getCarByBrand("tata"))),
onCase("maruti").then(exec(carsClient.getCarByBrand("maruti"))),
onCase("ford").then(exec(carsClient.getCarByBrand("ford")))
));
f) doSwitchOrElse
doSwitchOrElse is a control structure that allows you to perform different actions based on a value evaluated at runtime. It's similar to doSwitch, but it provides an else block that is executed if none of the specified cases match. This is useful when you have multiple possible values to check and a default action to take if no cases match.
ScenarioBuilder doSwitchOrElse = scenario("do switch or else condition")
.exec(session -> session.set("brand", "#{brand}"))
.exec(doSwitchOrElse("#{brand}").on(
onCase("tata").then(exec(carsClient.getCarByBrand("tata"))),
onCase("maruti").then(exec(carsClient.getCarByBrand("maruti"))),
onCase("ford").then(exec(carsClient.getCarByBrand("ford")))
).orElse(
exec(carsClient.getCarByBrand("tata"))
));
g) randomSwitch
The randomSwitch is a control structure that allows you to randomly choose between multiple actions.randomSwitch can be used to emulate simple Markov chains. A Markov Chain is a powerful tool for modeling random processes where the future depends only on the present state, not the history of how the system arrived at that state. Percentages sum can’t exceed 100%.
ScenarioBuilder randomSwitch = scenario("random switch condition")
.exec(randomSwitch().on(
percent(60.0).then(exec(carsClient.getCarByBrand("tata"))),
percent(20.0).then(exec(carsClient.getCarByBrand("maruti"))),
percent(20.0).then(exec(carsClient.getCarByBrand("ford")))
));
-
60% chance to execute a request to get a car by brand "tata".
-
20% chance to execute a request to get a car by brand "maruti".
-
20% chance to execute a request to get a car by brand "ford".
h) randomSwitchOrElse
It's similar to randomSwitch, but it provides an else block that is executed if none of the specified cases match.
ScenarioBuilder randomSwitchOrElse = scenario("random switch or Else condition")
.exec(randomSwitchOrElse().on(
percent(60.0).then(exec(carsClient.getCarByBrand("tata"))),
percent(20.0).then(exec(carsClient.getCarByBrand("maruti"))),
percent(20.0).then(exec(carsClient.getCarByBrand("ford")))
).orElse(
exec(carsClient.getCarByBrand("tata"))
));
i) uniformRandomSwitch
uniformRandomSwitch is a control structure that allows
you to randomly select one action from a set of alternatives, with equal
probability for each action. This means that each action has the same
chance of being selected, as opposed to the randomSwitch, where you can specify different probabilities (weights) for each
action.
The uniformRandomSwitch is particularly useful when you want to simulate a truly random selection between different actions, without assigning specific probabilities or weights.
ScenarioBuilder uniformRandomSwitch = scenario("uniform random switch")
.exec(uniformRandomSwitch().on(
exec(carsClient.getCarByBrand("tata")),
exec(carsClient.getCarByBrand("maruti")),
exec(carsClient.getCarByBrand("ford"))
));
j) roundRobinSwitch
roundRobinSwitch is a control structure that allows you to cycle through a set of actions in a round-robin fashion. This means it will execute each action in turn, one after the other, repeatedly cycling through the list of action.
ScenarioBuilder roundRobinSwitch = scenario("round robin switch")
.exec(roundRobinSwitch().on(
exec(carsClient.getCarByBrand("tata")),
exec(carsClient.getCarByBrand("maruti")),
exec(carsClient.getCarByBrand("ford"))
));
Next, it executes a request to get a car by brand "maruti".
And third times, it executes a request to get a car by brand "ford" and from fourth it executes a request to get a car by brand "tata" and the cycle goes on.
We can use loops and conditional statements together to make the scenarios more realistic. For example:
ScenarioBuilder doSwitchAndRepeat = scenario("Do switch and Repeat loop")
.exec(doSwitch("#{brand}").on(
onCase("tata").then(repeat(2).on(
exec(carsClient.getCarByBrand("tata")))),
onCase("maruti").then(repeat(3).on(
exec(carsClient.getCarByBrand("maruti")))),
onCase("ford").then(repeat(4).on(
exec(carsClient.getCarByBrand("ford")))
)));
That is all for Loops and Conditions, in next article we will explore more features of gatling. Till then, Happy Load Testing! 🚀