In a Gatling simulation, where do you register an assertions chain, and what does each link of that chain select?
answer
- Registered on setUp, judged afterwards
- Scope, statistic, metric, condition
- assertions(...) takes as many as you like
- All of them ANDed; one failure is enough
- details("Checkout").responseTime().percentile(95.0).lt(800)
basics
~10 sYou register them with assertions(...) on the setUp call, in the Simulation constructor. Each assertion chains a scope, then a statistic, then a metric, then a condition - for example details("Checkout").responseTime().percentile(95.0).lt(800).
solid answer
~30 sAssertions are pass/fail rules over the finished run's global statistics, registered by calling `assertions(...)` on what `setUp(...)` returns, inside the `Simulation` constructor. Each one chains a **scope** (`global`, `forAll` or `details(path)`), a **statistic** (`responseTime`, `allRequests`, `failedRequests`, `successfulRequests` or `requestsPerSec`), a **metric** that reduces it to one number (`max`, `mean`, `percentile(v)`, `count`, `percent`...), and a **condition** (`lt`, `gte`, `between`, `is`...). `assertions(...)` takes as many as you like and they are ANDed: one failure fails the run. `requestsPerSec` is the exception — it carries no metric link and goes straight to the condition.
code
java · 15 linesimport io.gatling.javaapi.core.*;
import static io.gatling.javaapi.core.CoreDsl.*;
public class CheckoutGate extends Simulation {
public CheckoutGate() {
ScenarioBuilder scn = scenario("checkout");
setUp(scn.injectOpen(atOnceUsers(1)))
.assertions(
details("Checkout").responseTime().percentile(95.0).lt(800),
global().failedRequests().count().lt(10L)
);
}
}go deeper
Be ready to name the four links in order and to write one complete assertion from memory, including where the assertions call attaches.
Be ready to explain why the compiler rejects illegal statistic and metric pairings, and why requestsPerSec has one link fewer than the others.
Be ready to say what an assertion can and cannot do about a run in progress, and where the verdict and its actual value are reported afterwards.
Be ready to argue what belongs in a simulation's assertion block versus in the pipeline step that runs it, given that every rule is ANDed into a single verdict.
## What a Gatling assertion is A Gatling **assertion** is a pass/fail rule over the **global statistics** of a finished run. It is not a per-response check: nothing in an assertion looks at an individual reply while the run is in flight. You declare the rules up front, Gatling runs the simulation, and only afterwards does it compute the run's statistics and test your rules against them. Assertions are registered by calling `assertions(...)` on the object that `setUp(...)` returns, inside the `Simulation` constructor: ```java setUp(scn.injectOpen(atOnceUsers(1))) .assertions( details("Checkout").responseTime().percentile(95.0).lt(800), global().failedRequests().count().lt(10L) ); ``` `assertions(...)` is variadic and takes as many assertions as you like. They are **combined with AND**: every one must hold, and the run fails if even one does not. ## The chain, link by link Each individual assertion is built by chaining four kinds of link, always in this order: | link | what it selects | the values | |---|---|---| | **scope** | which requests the statistic is computed from | `global`, `forAll`, `details(path)` | | **statistic** | which quantity is being judged | `responseTime`, `allRequests`, `failedRequests`, `successfulRequests`, `requestsPerSec` | | **metric** | how that quantity becomes one number | `min`, `max`, `mean`, `stdDev`, `percentile1`–`percentile4`, `percentile(v)` for response time; `count`, `percent` for the three count statistics | | **condition** | the test applied to that number | `lt`, `lte`, `gt`, `gte`, `between`, `around`, `deviatesAround`, `is`, `in` | ## The ladder is type-fixed, and one statistic is shorter Each link returns a different builder type, so the compiler enforces both the order and the legal combinations. You cannot reach a response-time reducer from a count statistic or the other way round: - `responseTime()` yields a time-metric stage, so only the time reducers are reachable. `global().responseTime().percent()` does not compile. - `allRequests()`, `failedRequests()` and `successfulRequests()` yield a count-metric stage that exposes exactly two methods, `count()` and `percent()`. `global().failedRequests().max()` does not compile. - `requestsPerSec()` **skips the metric link altogether** and goes straight to the condition, because there is only one number to reduce to — the mean rate over the run. `details("MyGroup").requestsPerSec().between(100.0, 1000.0)` is a complete assertion with three links. That last bullet is worth holding on to. Gatling's reference describes the chain as four steps without qualification, but `requestsPerSec` is genuinely a three-step chain, and looking for a `mean()` after it is the commonest way to get stuck. ## When they are evaluated Nothing is judged while users are running. After the simulation stops, Gatling parses the run's own log data, computes the statistics, and then validates every registered assertion against them. Each assertion prints its own line on the console with its verdict and the actual value it saw, and the generated HTML report gains an **Assertions** table with one OK/KO row per rule. Declaring assertions forces that log to be parsed even when report generation is switched off, because the verdict cannot be produced any other way. Two consequences follow directly. First, an assertion can never stop a run early — by the time it is evaluated there is nothing left to stop. Second, an assertion whose scope resolves to no data is a **failure**, not a silent pass: a `details(...)` path naming a request that never ran cannot be resolved, and an unresolvable assertion counts against the run. ## The commonest ways the chain refuses to compile Three mistakes account for most of them, and all three are the type system doing its job: 1. Reaching for a metric the statistic does not own — `percent()` after `responseTime()`, or `mean()` after `failedRequests()`. 2. Looking for a metric link after `requestsPerSec()`, which has none. 3. In Java and Kotlin, handing the wrong numeric literal to the condition. `count()` is typed on `Long` and `percent()` and `requestsPerSec()` on `Double`, so `count().lt(10)` and `percent().gt(95)` are rejected; they need `10L` and `95.0`. ## The spelling differs between the SDKs The link names are the same everywhere, but the surface is not: 1. **Scala** writes the intermediate links as parameterless members, without parentheses — `global.responseTime.max.lt(50)` — and builds a nested path with a `/` operator, `details("G" / "R")`. 2. **Java, Kotlin and the JavaScript/TypeScript SDK** write every link as a method call — `global().responseTime().max().lt(50)` — and pass a nested path as separate arguments, `details("G", "R")`. 3. The argument types bite in Java and Kotlin: `percent()` and `requestsPerSec()` are typed on `Double` and `count()` on `Long`, so `percent().gt(95.0)` and `count().lt(10L)` are required where Scala's numeric widening accepts a plain `95` or `10`. Never describe one of these as "the DSL" without naming the language — a sentence about `global.responseTime` is wrong in four of the five, and one about `global()` is wrong in Scala.
- Why does `global().failedRequests().max()` fail to compile?Because each link returns a different builder type. `failedRequests()` yields the count-metric stage, which exposes exactly `count()` and `percent()`. `max()` lives only on the time-metric stage that `responseTime()` returns. The ladder is enforced by types, so illegal statistic/metric pairings are rejected at compile time rather than at run time.
- Can an assertion abort a Gatling run once it is clearly going to fail?No. Assertions are evaluated only after the simulation has stopped, from the run's recorded statistics - by then there is nothing left to abort. If you need a running simulation to stop itself, that is a scenario-level concern, not an assertion. Assertions decide the verdict, never the run's length.
It reads like a sentence with a fixed word order: where to look, what to measure, how to boil it down to one number, and what that number must be. Get the order wrong and the compiler will not let you finish the sentence.
saying these in an interview costs you the question
- Thinking an assertion can stop a run while it is still going
- Calling percent() on responseTime, or max() on failedRequests
- Expecting a mean() link after requestsPerSec
- Believing a second assertion overrides rather than adds to the first