06 — Checks and Assertions
Checks validate HTTP responses and optionally extract values into the session. Assertions define pass/fail criteria for the whole simulation (used in CI).
Anatomy of a check
Status code checks
Response body checks
Substring / regex
.check(bodyString().is("OK"))
.check(substring("success").exists()) // check body contains substring
.check(bodyBytes().is("hello".getBytes()))
// Regex — first capture group
.check(regex("\"id\":(\\d+)").is("42"))
.check(regex("\"id\":(\\d+)").saveAs("userId"))
// Regex — all occurrences
.check(regex("\"tag\":\"(\\w+)\"").findAll().saveAs("tags"))
// Regex — count
.check(regex("\"item\"").count().is(5))
JSON path
Requires com.jayway.jsonpath:json-path (included transitively).
.check(jsonPath("$.status").is("active"))
.check(jsonPath("$.user.id").saveAs("userId"))
.check(jsonPath("$.items[0].name").is("Widget"))
.check(jsonPath("$.items.length()").ofInt().gt(0))
.check(jsonPath("$.items[*].id").findAll().saveAs("itemIds"))
Type conversions:
.check(jsonPath("$.count").ofInt().gte(1))
.check(jsonPath("$.price").ofDouble().lt(100.0))
.check(jsonPath("$.active").ofBoolean().is(true))
JMESPath (alternative JSON)
XPath (for XML / SOAP)
CSS selector
Header checks
.check(header("Content-Type").is("application/json"))
.check(header("Location").saveAs("location"))
.check(headerRegex("Set-Cookie", "session=(.+?);").saveAs("sessionCookie"))
Response time check (per-request)
Condition methods
| Method | Meaning |
|---|---|
.is(value) |
Exact equality |
.not(value) |
Not equal |
.in(v1, v2, …) |
Any of the values |
.gt(value) |
Greater than |
.gte(value) |
Greater than or equal |
.lt(value) |
Less than |
.lte(value) |
Less than or equal |
.exists() |
Value is present |
.notExists() |
Value is absent |
.isNull() |
Value is null |
.notNull() |
Value is not null |
For substring matching, use the
substring("text")check type instead of a condition method:.check(substring("success").exists())
Saving extracted values
Use .saveAs("key") after any condition (or instead of a condition):
.check(jsonPath("$.token").saveAs("authToken"))
.check(jsonPath("$.userId").ofInt().saveAs("userId"))
.check(header("Location").saveAs("resourceUrl"))
.check(regex("orderId=(\\w+)").saveAs("orderId"))
The saved value is then available in the session as #{authToken}, #{userId}, etc.
Optional vs mandatory checks
By default a check is mandatory — failure marks the request as KO.
Use .optional() to make it soft (missing value doesn't fail):
Multiple checks on one request
http("Login").post("/login")
.body(StringBody("""{"username":"#{username}","password":"#{password}"}"""))
.asJson()
.check(status().is(200))
.check(jsonPath("$.token").saveAs("authToken"))
.check(jsonPath("$.expiresIn").ofInt().gt(0))
Global simulation assertions
Placed in the setUp block — not on individual requests:
setUp(...)
.assertions(
// All requests
global().responseTime().mean().lt(200),
global().responseTime().percentile(95).lt(500),
global().responseTime().max().lt(2000),
global().successfulRequests().percent().gt(99.0),
global().failedRequests().count().lt(10L),
// Specific request by name
details("Login").responseTime().percentile(99).lt(1000),
details("Login").failedRequests().percent().lt(1.0),
// Specific group
details("Checkout flow").responseTime().percentile(95).lt(800)
);
Assertion failure causes a non-zero exit code — perfect for CI gates.
Kotlin note: is is a reserved keyword
In Kotlin, is is reserved. You have two options:
// Option 1: backticks
.check(status().`is`(200))
// Option 2: alias (preferred for readability)
.check(status().shouldBe(200))
The shouldBe alias works for all check validators where is would be used.
Full example
Java
ScenarioBuilder scn = scenario("Auth flow")
.exec(
http("Login").post("/auth/login")
.body(StringBody("""{"username":"#{username}","password":"#{password}"}"""))
.asJson()
.check(status().is(200))
.check(jsonPath("$.accessToken").saveAs("accessToken"))
.check(jsonPath("$.userId").ofInt().saveAs("userId"))
)
.exec(
http("Get profile").get("/users/#{userId}")
.header("Authorization", "Bearer #{accessToken}")
.check(status().is(200))
.check(jsonPath("$.email").exists())
);
Kotlin
val scn = scenario("Auth flow")
.exec(
http("Login").post("/auth/login")
.body(StringBody("""{"username":"#{username}","password":"#{password}"}"""))
.asJson()
.check(status().`is`(200))
.check(jsonPath("$.accessToken").saveAs("accessToken"))
.check(jsonPath("$.userId").ofInt().saveAs("userId"))
)
.exec(
http("Get profile").get("/users/#{userId}")
.header("Authorization", "Bearer #{accessToken}")
.check(status().`is`(200))
.check(jsonPath("$.email").exists())
)