skip to content

Why does a Gatling staircase written as incrementUsersPerSec(20).times(8).during(Duration.ofMinutes(2)) fail to compile, and how is the duration spelled instead?

level: middleimportance: should knowfreq 30%

answer

  1. Not every injection step ends in during
  2. A staircase has two durations, not one
  3. eachLevelLasting sets the level
  4. separatedByRampsLasting sets the ramp between levels

basics

~10 s

The stepped-level builders declare no during method. A staircase spells its durations with eachLevelLasting(d) for each level, and optionally separatedByRampsLasting(d) for the ramps between levels.

solid answer

~30 s

`during` belongs to Gatling's single-block injection steps — `rampUsers`, `constantUsersPerSec`, `rampUsersPerSec`, `constantConcurrentUsers`, `rampConcurrentUsers` — because each of those has exactly one duration to set. A staircase has two different durations, so it names them separately: `.eachLevelLasting(d)` for how long every level holds, and the optional `.separatedByRampsLasting(d)` for the ramps between them. Neither builder declares `during` at all, in the Java API or in the Scala core, so the call does not compile rather than misbehaving at run time. The fix is `incrementUsersPerSec(20).times(8).eachLevelLasting(Duration.ofMinutes(2))`.

code

java · 9 lines
java
setUp(
  scn.injectOpen(
    incrementUsersPerSec(20)
      .times(8)
      .eachLevelLasting(Duration.ofMinutes(2))
      .separatedByRampsLasting(Duration.ofSeconds(30))
      .startingFrom(20)
  )
);

go deeper

for a junior

Be ready to write the staircase chain from memory and to name eachLevelLasting rather than during as the call that sets how long a level holds.

for a middle

Be ready to explain why the builder splits the duration into two named calls, and why the wrong spelling is caught by the compiler rather than at run time.

for a senior

Be ready to spot a bare-number duration in a review and to say what the run actually lasted when someone read seconds as minutes.

for a principal

Be ready to argue for a house convention on duration spelling across a suite, so that level durations are never ambiguous between reviewers.

Every other closed-shape injection step in Gatling ends in `.during(duration)`, which makes `.during(...)` feel like the universal way to say how long a step runs. The staircase builders break that pattern deliberately, and they break it at compile time. ## Why `during` is missing A single-block step has exactly one duration, so one method can set it: | step | duration call | |---|---| | `rampUsers(n)` | `.during(d)` | | `constantUsersPerSec(rate)` | `.during(d)` | | `rampUsersPerSec(r1).to(r2)` | `.during(d)` | | `constantConcurrentUsers(n)` | `.during(d)` | | `rampConcurrentUsers(a).to(b)` | `.during(d)` | | `incrementUsersPerSec(inc).times(n)` | **`.eachLevelLasting(d)`** | | `incrementConcurrentUsers(inc).times(n)` | **`.eachLevelLasting(d)`** | A staircase is not one block. It expands into a list of blocks, and it has **two** independent time quantities: how long each level holds, and how long the linear ramp between two levels takes. One `during` could not say both without being ambiguous, so the builder gives each its own name: `eachLevelLasting` and `separatedByRampsLasting`. ## The failure is a compile error, not a surprise at run time The chain is a ladder of distinct types, and that is what catches the mistake: 1. `incrementUsersPerSec(20)` returns a stage whose only method is `times`. 2. `.times(8)` returns a stage whose only method is `eachLevelLasting`. 3. `.eachLevelLasting(d)` returns the composite step, which declares only `startingFrom` and `separatedByRampsLasting`. At no point in that ladder does a `during` method exist, in either the Java API or the Scala core. So the mistake is reported by the compiler — *cannot find symbol: method during* in Java, *value during is not a member of* in Scala — and never by a run that quietly applied the wrong shape. That is worth appreciating: because the level duration is mandatory and is the only way to move from `times` to a usable step, there is no way to accidentally build a staircase with no level duration at all. ## Nothing in the chain states the total run length This is the second thing the missing `during` implies, and it matters more in practice than the compile error. On a single-block step, `during(d)` **is** the length of that step. On a staircase, no call states the total at all — it is derived: * with no ramps: `levels x levelDuration` * with ramps and a non-zero `startingFrom`: `levels x levelDuration + (levels - 1) x rampDuration` * with ramps and a starting level of zero (`startingFrom` omitted or declared as `0`): `levels x (rampDuration + levelDuration)` So the answer to "how long does this profile run" is an arithmetic question about two or three numbers, not something you can read off one call. Eight levels of two minutes with thirty-second ramps and a declared non-zero starting level is 19 minutes 30 seconds, and nowhere does the source say so. ## Writing it correctly ```java // wrong - during is not declared anywhere on the staircase chain // incrementUsersPerSec(20).times(8).during(Duration.ofMinutes(2)) // right setUp( scn.injectOpen( incrementUsersPerSec(20) .times(8) .eachLevelLasting(Duration.ofMinutes(2)) .separatedByRampsLasting(Duration.ofSeconds(30)) .startingFrom(20) ) ); ``` That declares eight levels at 20, 40, 60, 80, 100, 120, 140 and 160 arrivals per second, each held for two minutes, with a thirty-second linear ramp between neighbouring levels. ## The duration argument itself Both staircase duration calls accept the same spellings as the rest of the injection DSL, and the spelling is the part that differs by SDK: * **Java and Kotlin** — a `java.time.Duration`, for example `Duration.ofMinutes(2)`. * **Scala** — a `scala.concurrent.duration` literal, for example `2.minutes`. * **JavaScript and TypeScript** — an object literal, for example `{ amount: 2, unit: "minutes" }`. * **All of them** — a bare number, which means **seconds**. `.eachLevelLasting(120)` is two minutes. The bare-number overload is why so much sample code reads `.eachLevelLasting(10)`; that is ten seconds, not ten minutes, and it is a quiet way to run a capacity test far shorter than intended. ## What the mistake usually signals Reaching for `.during(...)` almost always means the profile is being pictured as **one block of time that happens to rise**. A staircase is not that. It is a list of blocks — a constant-rate block per level, plus the ramp blocks that join them when ramps are declared — and the builder simply generates that list from four numbers. Once the profile is pictured as a list, `eachLevelLasting` stops feeling like an odd name for `during` and starts reading as what it is: the duration of one element of the list, applied uniformly to all of them. That also explains why there is no per-level duration. The builder derives the list from a single formula, and a list with a different duration on each element is not something four numbers can describe. Such a profile has to be written out as explicit alternating steps. ## What to carry away The staircase builders are the one family in Gatling's injection vocabulary that does not end in `during`. If a chain needs to express more than one duration, expect Gatling to have given each one its own name — and read the compile error as the DSL telling you which method the type you are holding actually offers.

  • What does `.eachLevelLasting(120)` mean, with no `Duration` wrapper?
    One hundred and twenty seconds. Every duration argument in Gatling's injection DSL has a bare-number overload that is interpreted as seconds, so `.eachLevelLasting(120)` and `.eachLevelLasting(Duration.ofMinutes(2))` are the same profile. The risk is reading a bare `10` in sample code as ten minutes.
  • Can the level durations of a staircase differ from one another?
    No. `eachLevelLasting` takes one duration and applies it to every level, and `separatedByRampsLasting` applies one ramp duration between every pair. A profile that needs a longer hold on the top level has to hand-chain the steps, or append a separate `constantUsersPerSec(...).during(...)` after the staircase.

saying these in an interview costs you the question

  • Assuming every Gatling injection step ends in during
  • Expecting one duration to cover levels and ramps alike
  • Reading a bare eachLevelLasting number as minutes
  • Believing the level duration can be left unset