Checks
Checks can be used to validate your request and extract elements which can be reused later
This page describes generic checks that can in theory be supported in all official protocols supported in Gatling.
Some protocols might implement specific checks, for example status
for HTTP. Those are not described here, but in the documentation specific to this protocol.
Concepts
Checks are used for 2 things:
- verifying that the response to a request matches some expectations
- capturing some elements in the response
Checks are typically attached to the parent object with the check
method.
For example, on an HTTP request:
http("Gatling").get("https://gatling.io")
.check(status().is(200))
http("Gatling").get("https://gatling.io")
.check(status().is(200))
http("Gatling").get("https://gatling.io")
.check(status().shouldBe(200))
http("Gatling").get("https://gatling.io")
.check(status.is(200))
You can also define multiple checks at once:
http("Gatling").get("https://gatling.io")
.check(
status().not(404),
status().not(500)
)
http("Gatling").get("https://gatling.io")
.check(
status().not(404),
status().not(500)
)
http("Gatling").get("https://gatling.io")
.check(
status().not(404),
status().not(500)
)
http("Gatling").get("https://gatling.io")
.check(
status.not(404),
status.not(500)
)
This API provides a dedicated DSL for chaining the following steps:
Generic check types
The following check types are generic and usually implemented on most official Gatling supported protocols.
responseTimeInMillis
Returns the response time of this request in milliseconds = the time between starting to send the request and finishing to receive the response.
.check(responseTimeInMillis().lte(100))
.check(responseTimeInMillis().lte(100))
.check(responseTimeInMillis().lte(100))
.check(responseTimeInMillis.lte(100))
bodyString
Return the full response body String.
.check(
bodyString().is("{\"foo\": \"bar\"}"),
bodyString().is(ElFileBody("expected-template.json"))
)
.check(
bodyString().is("{\"foo\": \"bar\"}"),
bodyString().is(ElFileBody("expected-template.json"))
)
.check(
bodyString().shouldBe("""{"foo": "bar"}"""),
bodyString().shouldBe(ElFileBody("expected-template.json"))
)
.check(
bodyString.is("""{"foo": "bar"}"""),
bodyString.is(ElFileBody("expected-template.json"))
)
bodyBytes
Return the full response body byte array.
.check(
bodyBytes().is("{\"foo\": \"bar\"}".getBytes(StandardCharsets.UTF_8)),
bodyBytes().is(RawFileBody("expected.json"))
)
.check(
bodyBytes().is("{\"foo\": \"bar\"}".getBytes(StandardCharsets.UTF_8)),
bodyBytes().is(RawFileBody("expected.json"))
)
.check(
bodyBytes().shouldBe("""{"foo": "bar"}""".toByteArray(StandardCharsets.UTF_8)),
bodyBytes().shouldBe(RawFileBody("expected.json"))
)
.check(
bodyBytes.is("""{"foo": "bar"}""".getBytes(StandardCharsets.UTF_8)),
bodyBytes.is(RawFileBody("expected.json"))
)
bodyLength
Return the length of the response body in bytes (without the overhead of computing the bytes array).
.check(bodyLength().is(1024))
.check(bodyLength().is(1024))
.check(bodyLength().shouldBe(1024))
.check(bodyLength.is(1024))
bodyStream
Return an InputStream of the full response body bytes, typically to transform the received bytes before processing them.
.check(bodyStream().transform(is -> {
// decode the Base64 stream into a String
try (InputStream base64Is = Base64.getDecoder().wrap(is)) {
return new String(base64Is.readAllBytes(), StandardCharsets.UTF_8);
} catch (IOException e) {
throw new RuntimeException("Impossible to decode Base64 stream");
}
}))
.check(bodyStream().transform { inputStream ->
// decode the Base64 stream into a String
Base64.getDecoder().wrap(inputStream).use { base64Is ->
String(base64Is.readAllBytes(), StandardCharsets.UTF_8)
}
})
.check(bodyStream.transform { is =>
// decode the Base64 stream into a String
Using(Base64.getDecoder.wrap(is)) { base64Is =>
new String(base64Is.readAllBytes(), StandardCharsets.UTF_8)
}
})
substring
This check looks for the indices of the occurrences of a given substring inside the response body text.
It takes one single parameter:
pattern
can be a plainString
, a Gatling Expression LanguageString
or a function.
.check(
// with a static value
// (identical to substring("expected").find().exists())
substring("expected"),
// with a a dynamic value computed from a Gatling Expression Language String
substring("#{expectedKey}"),
// with a dynamic value computed from a function
substring(session -> "expectedValue"),
substring("Error:").notExists(),
// this will save a List<Int>
substring("foo").findAll().saveAs("indices"),
// this will save the number of occurrences of foo
substring("foo").count().saveAs("counts")
)
.check(
// with a static value
// (identical to substring("expected").find().exists())
substring("expected"),
// with a a dynamic value computed from a Gatling Expression Language String
substring("#{expectedKey}"),
// with a dynamic value computed from a function
substring((session) => "expectedValue"),
substring("Error:").notExists(),
// this will save a List<Int>
substring("foo").findAll().saveAs("indices"),
// this will save the number of occurrences of foo
substring("foo").count().saveAs("counts")
)
.check(
// with a static value
// (identical to substring("expected").find().exists())
substring("expected"),
// with a dynamic value computed from a Gatling Expression Language String
substring("#{expectedKey}"),
// with a dynamic value computed from a function
substring { session -> "expectedValue" },
substring("Error:").notExists(),
// this will save a List<Int>
substring("foo").findAll().saveAs("indices"),
// this will save the number of occurrences of foo
substring("foo").count().saveAs("counts")
)
.check(
// with a static value
// (identical to substring("expected").find.exists)
substring("expected"),
// with a dynamic value computed from a Gatling Expression Language String
substring("#{expectedKey}"),
// with a dynamic value computed from a function
substring(session => "expectedValue"),
substring("Error:").notExists,
// this will save a List<Int>
substring("foo").findAll.saveAs("indices"),
// this will save the number of occurrences of foo
substring("foo").count.saveAs("counts")
)
regex
This check applies a Java regular expression pattern on the response body text.
It takes one single parameter:
pattern
can be a plainString
, a Gatling Expression LanguageString
or a function.
.check(
// with a static value without capture groups
regex("<td class=\"number\">"),
// with a Gatling EL without capture groups
regex("<td class=\"number\">ACC#{account_id}</td>"),
// with a static value with one single capture group
regex("/private/bank/account/(ACC[0-9]*)/operations.html")
)
.check(
// with a static value without capture groups
regex("<td class=\"number\">"),
// with a Gatling EL without capture groups
regex("<td class=\"number\">ACC#{account_id}</td>"),
// with a static value with one single capture group
regex("/private/bank/account/(ACC[0-9]*)/operations.html")
)
.check(
// with a static value without capture groups
regex("""<td class="number">"""),
// with a Gatling EL without capture groups
regex("""<td class="number">ACC#{account_id}</td>"""),
// with a static value with one single capture group
regex("/private/bank/account/(ACC[0-9]*)/operations.html")
)
.check(
// with a static value without capture groups
regex("""<td class="number">"""),
// with a Gatling EL without capture groups
regex("""<td class="number">ACC#{account_id}</td>"""),
// with a static value with one single capture group
regex("/private/bank/account/(ACC[0-9]*)/operations.html")
)
"""my "non-escaped" string"""
.
This simplifies the writing and reading of regular expressions.By default, it can extract 0 or 1 capture group, so the extracted type is String
.
If your pattern contains more than one capture group, you must specify it with an extra step:
// In Java, use captureGroups(numberOfCaptureGroups) to capture List<String>
.check(
regex("foo(.*)bar(.*)baz").captureGroups(2)
)
// In Java, use captureGroups(numberOfCaptureGroups) to capture List<String>
.check(
regex("foo(.*)bar(.*)baz").captureGroups(2)
)
// In Kotlin, use captureGroups(numberOfCaptureGroups) to capture List<String>
.check(
regex("foo(.*)bar(.*)baz").captureGroups(2)
)
// In Scala, use ofType[T] to capture String tuples (up to 8)
.check(
regex("foo(.*)bar(.*)baz").ofType[(String, String)]
)
xpath
This check applies an XPath query on an XML response body.
It takes two parameters:
expression
can be a plainString
, a Gatling Expression LanguageString
or a function.namespaces
is an optional List of couples of (prefix, uri). It’s mandatory as soon as your document contains namespaces.
.check(
// simple expression for a document that doesn't use namespaces
xpath("//input[@id='text1']/@value"),
// mandatory namespaces parameter for a document that uses namespaces
xpath("//foo:input[@id='text1']/@value", Map.of("foo", "http://foo.com"))
)
.check(
// simple expression for a document that doesn't use namespaces
xpath("//input[@id='text1']/@value"),
// mandatory namespaces parameter for a document that uses namespaces
xpath("//foo:input[@id='text1']/@value", { "foo": "http://foo.com" })
)
.check(
// simple expression for a document that doesn't use namespaces
xpath("//input[@id='text1']/@value"),
// mandatory namespaces parameter for a document that uses namespaces
xpath("//foo:input[@id='text1']/@value", mapOf("foo" to "http://foo.com"))
)
.check(
// simple expression for a document that doesn't use namespaces
xpath("//input[@id='text1']/@value"),
// mandatory namespaces parameter for a document that uses namespaces
xpath("//foo:input[@id='text1']/@value", Map("foo" -> "http://foo.com"))
)
XPath only works on well-formed XML documents, which HTML is not.
If you’re looking for path based engine for parsing HTML documents, please have a look at our CSS selectors support.
jsonPath
JsonPath is an XPath-like syntax for JSON.
It takes one single parameter:
expression
can be a plainString
, a Gatling Expression LanguageString
or a function.
.check(
// with a static value
jsonPath("$..foo.bar[2].baz"),
// with a Gatling EL String
jsonPath("$..foo.bar[#{index}].baz"),
// with a function
jsonPath(session -> "$..foo.bar[" + session.getInt("session") + "].baz")
)
.check(
// with a static value
jsonPath("$..foo.bar[2].baz"),
// with a Gatling EL String
jsonPath("$..foo.bar[#{index}].baz"),
// with a function
jsonPath((session) => "$..foo.bar[" + session.get("session") + "].baz")
)
.check(
// with a static value
jsonPath("$..foo.bar[2].baz"),
// with a Gatling EL String
jsonPath("$..foo.bar[#{index}].baz"),
// with a function
jsonPath { session -> "$..foo.bar[${session.getInt("session")}].baz" }
)
.check(
// with a static value
jsonPath("$..foo.bar[2].baz"),
// with a Gatling EL String
jsonPath("$..foo.bar[#{index}].baz"),
// with a function
jsonPath(session => s"$$..foo.bar[${session("session").as[Int]}].baz")
)
By default, it extracts Strings, meaning that non String values get serialized back into JSON. You can tell Gatling the expected type with an extra step. Note that the check will then fail if the actual value doesn’t match the expected type.
.check(
jsonPath("$.foo").ofString(),
jsonPath("$.foo").ofBoolean(),
jsonPath("$.foo").ofInt(),
jsonPath("$.foo").ofLong(),
jsonPath("$.foo").ofDouble(),
// JSON array
jsonPath("$.foo").ofList(),
// JSON object
jsonPath("$.foo").ofMap(),
// anything
jsonPath("$.foo").ofObject()
)
.check(
jsonPath("$.foo").ofString(),
jsonPath("$.foo").ofBoolean(),
jsonPath("$.foo").ofInt(),
jsonPath("$.foo").ofLong(),
jsonPath("$.foo").ofDouble(),
// JSON array
jsonPath("$.foo").ofList(),
// JSON object
jsonPath("$.foo").ofMap(),
// anything
jsonPath("$.foo").ofObject()
)
.check(
jsonPath("$.foo").ofString(),
jsonPath("$.foo").ofBoolean(),
jsonPath("$.foo").ofInt(),
jsonPath("$.foo").ofLong(),
jsonPath("$.foo").ofDouble(),
// JSON array
jsonPath("$.foo").ofList(),
// JSON object
jsonPath("$.foo").ofMap(),
// anything
jsonPath("$.foo").ofObject()
)
.check(
jsonPath("$.foo").ofType[String],
jsonPath("$.foo").ofType[Boolean],
jsonPath("$.foo").ofType[Int],
jsonPath("$.foo").ofType[Long],
jsonPath("$.foo").ofType[Double],
// JSON array
jsonPath("$.foo").ofType[Seq[Any]],
// JSON object
jsonPath("$.foo").ofType[Map[String, Any]],
// anything
jsonPath("$.foo").ofType[Any]
)
For example, considering the following JSON payload:
{
"foo": 1,
"bar": "baz"
}
… this is how you would extract an integer value:
.check(
jsonPath("$.foo").ofInt().is(1)
)
.check(
jsonPath("$.foo").ofInt().is(1)
)
.check(
jsonPath("$.foo").ofInt().shouldBe(1)
)
.check(
jsonPath("$.foo").ofType[Int].is(1)
)
jsonpJsonPath
Same as jsonPath
but for JSONP.
jmesPath
JMESPath is a query language for JSON.
jsonPath
that it comes with a full grammar and a Test Compliance Kit to validate implementations.
As a result, an expression tested with the online evaluator is guaranteed to work in Gatling too.It takes one single parameter:
- expression can be a plain
String
, a Gatling Expression LanguageString
or a function.
.check(
// with a static value
jmesPath("foo.bar[2].baz"),
// with a Gatling EL String
jmesPath("foo.bar[#{index}].baz"),
// with a function
jmesPath(session -> "foo.bar[" + session.getInt("session") + "].baz")
)
.check(
// with a static value
jmesPath("foo.bar[2].baz"),
// with a Gatling EL String
jmesPath("foo.bar[#{index}].baz"),
// with a function
jmesPath((session) => "foo.bar[" + session.get("session") + "].baz")
)
.check(
// with a static value
jmesPath("foo.bar[2].baz"),
// with a Gatling EL String
jmesPath("foo.bar[#{index}].baz"),
// with a function
jmesPath { session -> "foo.bar[${session.getInt("session")}].baz" }
)
.check(
// with a static value
jmesPath("foo.bar[2].baz"),
// with a Gatling EL String
jmesPath("foo.bar[#{index}].baz"),
// with a function
jmesPath(session => s"foo.bar[${session("session").as[Int]}].baz")
)
By default, it extracts Strings, meaning that non String values get serialized back into JSON. You can tell Gatling the expected type with an extra step. Note that the check will then fail is the actual value doesn’t match the expected type.
.check(
jmesPath("foo").ofString(),
jmesPath("foo").ofBoolean(),
jmesPath("foo").ofInt(),
jmesPath("foo").ofLong(),
jmesPath("foo").ofDouble(),
// JSON array
jmesPath("foo").ofList(),
// JSON object
jmesPath("foo").ofMap(),
// anything
jmesPath("foo").ofObject()
)
.check(
jmesPath("foo").ofString(),
jmesPath("foo").ofBoolean(),
jmesPath("foo").ofInt(),
jmesPath("foo").ofLong(),
jmesPath("foo").ofDouble(),
// JSON array
jmesPath("foo").ofList(),
// JSON object
jmesPath("foo").ofMap(),
// anything
jmesPath("foo").ofObject()
)
.check(
jmesPath("foo").ofString(),
jmesPath("foo").ofBoolean(),
jmesPath("foo").ofInt(),
jmesPath("foo").ofLong(),
jmesPath("foo").ofDouble(),
// JSON array
jmesPath("foo").ofList(),
// JSON object
jmesPath("foo").ofMap(),
// anything
jmesPath("foo").ofObject()
)
.check(
jmesPath("foo").ofType[String],
jmesPath("foo").ofType[Boolean],
jmesPath("foo").ofType[Int],
jmesPath("foo").ofType[Long],
jmesPath("foo").ofType[Double],
// JSON array
jmesPath("foo").ofType[Seq[Any]],
// JSON object
jmesPath("foo").ofType[Map[String, Any]],
// anything
jmesPath("foo").ofType[Any]
)
For example, considering the following JSON payload:
{
"foo": 1,
"bar": "baz"
}
… this is how you would extract an integer value:
.check(
jmesPath("foo").ofInt().is(1)
)
.check(
jmesPath("foo").ofInt().is(1)
)
.check(
jmesPath("foo").ofInt().shouldBe(1)
)
.check(
jmesPath("foo").ofType[Int].is(1)
)
registerJmesPathFunctions(io.burt.jmespath.function.Function*)
to register custom functions.jsonpJmesPath
Same as jmesPath
but for JSONP.
css
This checks lets you apply CSS Selectors on HTML response body text.
It takes two parameters:
selector
can be a plainString
, a Gatling Expression LanguageString
or a function.attribute
is an optional staticString
if you want to target an attribute of the selected DOM nodes.
.check(
// with a static value
css("#foo"),
// with a Gatling EL String
css("##{id}"),
// with a function
css(session -> "#" + session.getString("id")),
// with an attribute
css("article.more a", "href")
)
.check(
// with a static value
css("#foo"),
// with a Gatling EL String
css("##{id}"),
// with a function
css((session) => "#" + session.get("id")),
// with an attribute
css("article.more a", "href")
)
.check(
// with a static value
css("#foo"),
// with a Gatling EL String
css("##{id}"),
// with a function
css { session -> "#${session.getString("id")}" },
// with an attribute
css("article.more a", "href")
)
.check(
// with a static value
css("#foo"),
// with a Gatling EL String
css("##{id}"),
// with a function
css(session => s"#${session("id").as[String]}"),
// with an attribute
css("article.more a", "href")
)
By default, it extracts Strings. In particular, if you haven’t defined the attribute
parameter, it will extract the node text content. You can force Gatling to actually capture the jodd.lagarto.dom.Node with an extra step:
.check(
css("article.more a", "href").ofNode()
)
.check(
css("article.more a", "href").ofNode()
)
.check(
css("article.more a", "href").ofType[Node]
)
form
This check uses a CSS Selector to capture all the defined or selected input parameters in a form tag into a Map.
Map values can be multivalued depending on if the input is multivalued or not
(input with multiple
attribute set, or multiple occurrences of the same input name, except for radio).
It takes one single parameter:
selector
can be a plainString
, a Gatling Expression LanguageString
or a function.
.check(
form("myForm")
)
.check(
form("myForm")
)
.check(
form("myForm")
)
.check(
form("myForm")
)
md5
and sha1
This check computes a checksum of the response body. This can be useful to verify that a downloaded resource has not been corrupted in the process.
.check(
md5().is("???"),
sha1().is("???")
)
.check(
md5().is("???"),
sha1().is("???")
)
.check(
md5().shouldBe("???"),
sha1().shouldBe("???")
)
.check(
md5.is("???"),
sha1.is("???")
)
Extracting
The extraction step of the check DSL lets you filter the desired occurrence(s).
find
.find
Filter one single element.
Target the first or only possible occurrence, depending on the check type.
If the check can capture multiple elements, find
is identical to find(0)
.
It comes in 2 flavors:
- parameterless, identical to
find(0)
- with an integer parameter that is a 0 based rank of the occurrence. Only available on checks that can return multiple values.
.check(
// those 2 are identical because jmesPath can only return 1 value
// so find is better ommitted
jmesPath("foo"),
jmesPath("foo").find(),
// jsonPath can return multiple values
// those 3 are identical so find is better ommitted
jsonPath("$.foo"),
jsonPath("$.foo").find(),
jsonPath("$.foo").find(0),
// captures the 2nd occurrence
jsonPath("$.foo").find(1)
)
.check(
// those 2 are identical because jmesPath can only return 1 value
// so find is better ommitted
jmesPath("foo"),
jmesPath("foo").find(),
// jsonPath can return multiple values
// those 3 are identical so find is better ommitted
jsonPath("$.foo"),
jsonPath("$.foo").find(),
jsonPath("$.foo").find(0),
// captures the 2nd occurrence
jsonPath("$.foo").find(1)
)
.check(
// those 2 are identical because jmesPath can only return 1 value
// so find is better ommitted
jmesPath("foo"),
jmesPath("foo").find(),
// jsonPath can return multiple values
// those 3 are identical so find is better ommitted
jsonPath("$.foo"),
jsonPath("$.foo").find(),
jsonPath("$.foo").find(0),
// captures the 2nd occurrence
jsonPath("$.foo").find(1)
)
.check(
// those 2 are identical because jmesPath can only return 1 value
// so find is better ommitted
jmesPath("foo"),
jmesPath("foo").find,
// jsonPath can return multiple values
// those 3 are identical so find is better ommitted
jsonPath("$.foo"),
jsonPath("$.foo").find,
jsonPath("$.foo").find(0),
// captures the 2nd occurrence
jsonPath("$.foo").find(1)
)
findAll
Return all the occurrences. Only available on checks that can return multiple values.
.check(
jsonPath("$.foo").findAll()
)
.check(
jsonPath("$.foo").findAll()
)
.check(
jsonPath("$.foo").findAll()
)
.check(
jsonPath("$.foo").findAll
)
findRandom
Return a random occurrence. Only available on checks that can return multiple values.
It comes in 2 flavors:
- parameterless, identical to
findRandom(1)
- with a
num
int parameter and an optionalfailIfLess
boolean parameter (default false, check will pick as many as possible) to extract several occurrences and optionally fail is the number of actual matches is less than the expected number.
.check(
// identical to findRandom(1, false)
jsonPath("$.foo").findRandom(),
// identical to findRandom(1, false)
jsonPath("$.foo").findRandom(1),
// identical to findRandom(3, false)
// best effort to pick 3 entries, less if not enough
jsonPath("$.foo").findRandom(3),
// fail if less than 3 overall captured values
jsonPath("$.foo").findRandom(3, true)
)
.check(
// identical to findRandom(1, false)
jsonPath("$.foo").findRandom(),
// identical to findRandom(1, false)
jsonPath("$.foo").findRandom(1),
// identical to findRandom(3, false)
// best effort to pick 3 entries, less if not enough
jsonPath("$.foo").findRandom(3),
// fail if less than 3 overall captured values
jsonPath("$.foo").findRandom(3, true)
)
.check(
// identical to findRandom(1, false)
jsonPath("$.foo").findRandom(),
// identical to findRandom(1, false)
jsonPath("$.foo").findRandom(1),
// identical to findRandom(3, false)
// best effort to pick 3 entries, less if not enough
jsonPath("$.foo").findRandom(3),
// fail if less than 3 overall captured values
jsonPath("$.foo").findRandom(3, true)
)
.check(
// identical to findRandom(1, false)
jsonPath("$.foo").findRandom,
// identical to findRandom(1, false)
jsonPath("$.foo").findRandom(1),
// identical to findRandom(3, false)
// best effort to pick 3 entries, less if not enough
jsonPath("$.foo").findRandom(3),
// fail if less than 3 overall captured values
jsonPath("$.foo").findRandom(3, failIfLess = true)
)
count
Returns the number of occurrences. Only available on checks that can return multiple values.
.check(
jsonPath("$.foo").count()
)
.check(
jsonPath("$.foo").count()
)
.check(
jsonPath("$.foo").count()
)
.check(
jsonPath("$.foo").count
)
Transforming
Transforming is an optional step that lets you transform the result of the extraction before trying to match it or save it.
withDefault
This optional step lets you provide a default value in case the previous step failed to capture anything.
It takes one single parameter:
defaultValue
can be a plainString
, a Gatling Expression LanguageString
or a function that must return the same type as the expected value
.check(
jsonPath("$.foo")
.withDefault("defaultValue")
)
.check(
jsonPath("$.foo")
.withDefault("defaultValue")
)
.check(
jsonPath("$.foo")
.withDefault("defaultValue")
)
.check(
jsonPath("$.foo")
.withDefault("defaultValue")
)
transform
This step lets you pass a function that will only be triggered if the previous step was able to capture something.
It takes one single parameter:
function
is of typeX
to another possibly different typeX2
.check(
jsonPath("$.foo")
// append "bar" to the value captured in the previous step
.transform(string -> string + "bar")
)
.check(
jsonPath("$.foo")
// append "bar" to the value captured in the previous step
.transform((string) => string + "bar")
)
.check(
jsonPath("$.foo")
// append "bar" to the value captured in the previous step
.transform { string -> string + "bar" }
)
.check(
jsonPath("$.foo")
// append "bar" to the value captured in the previous step
.transform(string => string + "bar")
)
transformWithSession
This step is a variant of transform
that lets you access the Session
is order to compute the returned result.
It takes one single parameter:
function
is of type(X, Session)
to another possibly different typeX2
.check(
jsonPath("$.foo")
// append the value of the "bar" attribute
// to the value captured in the previous step
.transformWithSession((string, session) -> string + session.getString("bar"))
)
.check(
jsonPath("$.foo")
// append the value of the "bar" attribute
// to the value captured in the previous step
.transformWithSession((string, session) => string + session.get("bar"))
)
.check(
jsonPath("$.foo")
// append the value of the "bar" attribute
// to the value captured in the previous step
.transformWithSession { string, session -> string + session.getString("bar") }
)
.check(
jmesPath("foo")
// append the value of the "bar" attribute
// to the value captured in the previous step
.transformWithSession((string, session) => string + session("bar").as[String])
)
transformOption
In contrary to transform
, this step is always invoked, even when the previous step failed to capture anything.
.check(
jmesPath("foo")
// extract can be null
.transform(extract -> Optional.of(extract).orElse("default"))
)
.check(
jmesPath("foo")
// extract can be null
.transform((extract) => extract !== null ? extract : "default")
)
.check(
jmesPath("foo")
// extract can be null
.transform { extract -> Optional.of(extract).orElse("default") }
)
.check(
jmesPath("foo")
// extract is of type Option[String]
.transformOption(extract => extract.orElse(Some("default")))
)
withDefault
is probably a more convenient way.transformOptionWithSession
This step is a variant of transformOption
that lets you access the Session
is order to compute the returned result.
.check(
jmesPath("foo")
// extract can be null
.transformWithSession((extract, session) ->
Optional.of(extract).orElse(session.getString("default"))
)
)
.check(
jmesPath("foo")
// extract can be null
.transformWithSession((extract, session) =>
extract !== null ? extract : session.get("default")
)
)
.check(
jmesPath("foo")
// extract can be null
.transformWithSession { extract, session ->
Optional.of(extract).orElse(session.getString("default"))
}
)
.check(
jmesPath("foo")
// extract is of type Option[String]
.transformOptionWithSession((extract, session) =>
extract.orElse(Some(session("default").as[String]))
)
)
Validating
exists
.is
Validate that the value is equal to the expected one.
It takes one single parameter:
expected
can be a plain value whose type matches the extracted value, a Gatling Expression LanguageString
or a function.
.check(
// with a static value
jmesPath("foo").is("expected"),
// with a Gatling EL String (BEWARE DIFFERENT METHOD)
jmesPath("foo").isEL("#{expected}"),
// with a function
jmesPath("foo").is(session -> session.getString("expected"))
)
.check(
// with a static value
jmesPath("foo").is("expected"),
// with a Gatling EL String (BEWARE DIFFERENT METHOD)
jmesPath("foo").isEL("#{expected}"),
// with a function
jmesPath("foo").is((session) => session.get("expected"))
)
.check(
// with a static value
jmesPath("foo").shouldBe("expected"),
// with a Gatling EL String (BEWARE DIFFERENT METHOD)
jmesPath("foo").isEL("#{expected}"),
// with a function
jmesPath("foo").shouldBe { session -> session.getString("expected") }
)
.check(
// with a static value
jmesPath("foo").is("expected"),
// with a Gatling EL String
jmesPath("foo").is("#{expected}"),
// with a function
jmesPath("foo").is(session => session("expected").as[String])
)
is
is a reserved keyword in Kotlin.
You can either protect it with backticks `is`
or use the shouldBe
alias instead.isNull
Validate that the extracted value is null, typically a JSON value.
.check(
jmesPath("foo")
.isNull()
)
.check(
jmesPath("foo")
.isNull()
)
.check(
jmesPath("foo")
.isNull()
)
.check(
jmesPath("foo")
.isNull
)
not
Validate that the extracted value is different from the expected one.
It takes one single parameter:
unexpected
can be a plain value whose type matches the extracted value, a Gatling Expression LanguageString
or a function.
.check(
// with a static value
jmesPath("foo").not("unexpected"),
// with a Gatling EL String (BEWARE DIFFERENT METHOD)
jmesPath("foo").notEL("#{unexpected}"),
// with a function
jmesPath("foo").not(session -> session.getString("unexpected"))
)
.check(
// with a static value
jmesPath("foo").not("unexpected"),
// with a Gatling EL String (BEWARE DIFFERENT METHOD)
jmesPath("foo").notEL("#{unexpected}"),
// with a function
jmesPath("foo").not((session) => session.get("unexpected"))
)
.check(
// with a static value
jmesPath("foo").not("unexpected"),
// with a Gatling EL String (BEWARE DIFFERENT METHOD)
jmesPath("foo").notEL("#{unexpected}"),
// with a function
jmesPath("foo").not { session -> session.getString("unexpected") }
)
.check(
// with a static value
jmesPath("foo").not("unexpected"),
// with a Gatling EL String
jmesPath("foo").not("#{unexpected}"),
// with a function
jmesPath("foo").not(session => session("unexpected").as[String])
)
notNull
Validate that the extracted value is not null, typically a JSON value.
.check(
jmesPath("foo").notNull()
)
.check(
jmesPath("foo").notNull()
)
.check(
jmesPath("foo").notNull()
)
.check(
jmesPath("foo").notNull
)
exists
Validate that the extracted value exists.
.check(
jmesPath("foo").exists()
)
.check(
jmesPath("foo").exists()
)
.check(
jmesPath("foo").exists()
)
.check(
jmesPath("foo").exists
)
notExists
Validate that the check didn’t match and failed to extract anything.
.check(
jmesPath("foo").notExists()
)
.check(
jmesPath("foo").notExists()
)
.check(
jmesPath("foo").notExists()
)
.check(
jmesPath("foo").notExists
)
in
Validate that the extracted value belongs to a given sequence or vararg.
.check(
// with a static values varargs
jmesPath("foo").in("value1", "value2"),
// with a static values List
jmesPath("foo").in(List.of("value1", "value2")),
// with a Gatling EL String that points to a List in Session (BEWARE DIFFERENT METHOD)
jmesPath("foo").inEL("#{expectedValues}"),
// with a function
jmesPath("foo").in(session -> List.of("value1", "value2"))
)
.check(
// with a static values varargs
jmesPath("foo").in("value1", "value2"),
// with a static values List
jmesPath("foo").in(...["value1", "value2"]),
// with a Gatling EL String that points to a List in Session (BEWARE DIFFERENT METHOD)
jmesPath("foo").inEL("#{expectedValues}"),
// with a function
jmesPath("foo").in((session) => ["value1", "value2"])
)
.check(
// with a static values varargs
jmesPath("foo").within("value1", "value2"),
// with a static values List
jmesPath("foo").within(listOf("value1", "value2")),
// with a Gatling EL String that points to a List in Session (BEWARE DIFFERENT METHOD)
jmesPath("foo").withinEL("#{expectedValues}"),
// with a function
jmesPath("foo").within { session -> listOf("value1", "value2") }
)
.check(
// with a static values varargs
jmesPath("foo").in("value1", "value2"),
// with a static values Seq
jmesPath("foo").in(Seq("value1", "value2")),
// with a Gatling EL String that points to a Seq in Session
jmesPath("foo").in("#{expectedValues}"),
// with a function
jmesPath("foo").in(session => Seq("value1", "value2"))
)
in
is a reserved keyword in Kotlin.
You can either protect it with backticks `in`
or use the within
alias instead.optional
Allows for the target to be missing. In this case, the check won’t fail, the following steps won’t trigger, including saveAs, meaning possibly existing value won’t be replaced nor removed.
validate
You can supply your own validator.
It takes two parameters:
name
is the String that would be used to describe this part in case of a failure in the final error message.validator
is the validation logic function.
.check(
jmesPath("foo")
.validate(
"MyCustomValidator",
(actual, session) -> {
String prefix = session.getString("prefix");
if (actual == null) {
throw new NullPointerException("Value is missing");
} else if (!actual.startsWith(prefix)) {
throw new IllegalArgumentException("Value " + actual + " should start with " + prefix);
}
return actual;
})
)
.check(
jmesPath("foo")
.validate(
"MyCustomValidator",
(actual, session) => {
const prefix = session.get("prefix");
if (actual == null) {
throw Error("Value is missing");
} else if (!actual.startsWith(prefix)) {
throw Error("Value " + actual + " should start with " + prefix);
}
return actual;
})
)
.check(
jmesPath("foo")
.validate("MyCustomValidator") { actual, session ->
val prefix: String = session.getString("prefix")!!
if (actual == null) {
throw NullPointerException("Value is missing")
} else {
require(actual.startsWith(prefix)) { "Value $actual should start with $prefix" }
actual
}
}
)
.check(
jmesPath("foo")
.validate(
"MyCustomValidator",
(actual, session) => {
import io.gatling.commons.validation._
val prefix = session("prefix").as[String]
actual match {
case Some(value) if !value.startsWith(prefix) => Failure(s"Value $value should start with $prefix")
case None => Failure("Value is missing")
case _ => Success(actual)
}
})
)
Naming
name
Naming is an optional step for customizing the name of the check in the error message in case of a check failure.
It takes one single parameter:
name
can only be a static String.
.check(
jmesPath("foo").name("My custom error message")
)
.check(
jmesPath("foo").name("My custom error message")
)
.check(
jmesPath("foo").name("My custom error message")
)
.check(
jmesPath("foo").name("My custom error message")
)
Saving
saveAs
Saving is an optional step for storing the result of the check into the virtual user’s Session, so that it can be reused later. It’s only effective when the check is successful: it could match the response and passed validation.
It takes one single parameter:
key
can only be a static String.
.check(
jmesPath("foo").saveAs("key")
)
.check(
jmesPath("foo").saveAs("key")
)
.check(
jmesPath("foo").saveAs("key")
)
.check(
jmesPath("foo").saveAs("key")
)
Conditional checking
checkIf
checkIf
instead of check
.Only perform the checks when some condition holds.
// with a Gatling EL String condition that resolves a Boolean
.checkIf("#{bool}").then(
jmesPath("foo")
)
// with a function
.checkIf(session -> session.getString("key").equals("executeCheck")).then(
jmesPath("foo")
)
// with a Gatling EL String condition that resolves a Boolean
.checkIf("#{bool}").then(
jmesPath("foo")
)
// with a function
.checkIf((session) => session.get("key") === "executeCheck").then(
jmesPath("foo")
)
// with a Gatling EL String condition that resolves a Boolean
.checkIf("#{bool}").then(
jmesPath("foo")
)
// with a function
.checkIf { session -> session.getString("key").equals("executeCheck") }.then(
jmesPath("foo")
)
// with a Gatling EL String condition that resolves a Boolean
.checkIf("#{bool}") {
jsonPath("$..foo")
}
// with a function
.checkIf(session => session("key").as[String] == "executeCheck") {
jsonPath("$..foo")
}
Putting it all together
To help you understand the checks, here is a list of examples.
.check(
// check the HTTP status is 200
status().is(200),
// check the HTTP status is in [200, 210]
status().in(200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210),
// check the response body contains 5 https links
regex("https://(.*)").count().is(5),
// check the response body contains 2 https links,
// the first one to www.google.com and the second one to gatling.io
regex("https://(.*)/.*").findAll().is(List.of("www.google.com", "gatling.io")),
// check the response body contains a second occurrence of "someString"
substring("someString").find(1).exists(),
// check the response body does not contain "someString"
substring("someString").notExists()
)
.check(
// check the HTTP status is 200
status().is(200),
// check the HTTP status is in [200, 210]
status().in(200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210),
// check the response body contains 5 https links
regex("https://(.*)").count().is(5),
// check the response body contains 2 https links,
// the first one to www.google.com and the second one to gatling.io
regex("https://(.*)/.*").findAll().is(["www.google.com", "gatling.io"]),
// check the response body contains a second occurrence of "someString"
substring("someString").find(1).exists(),
// check the response body does not contain "someString"
substring("someString").notExists()
)
.check(
// check the HTTP status is 200
status().shouldBe(200),
// check the HTTP status is in [200, 210]
status().within(200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210),
// check the response body contains 5 https links
regex("https://(.*)").count().shouldBe(5),
// check the response body contains 2 https links,
// the first one to www.google.com and the second one to gatling.io
regex("https://(.*)/.*").findAll().shouldBe(listOf("www.google.com", "gatling.io")),
// check the response body contains a second occurrence of "someString"
substring("someString").find(1).exists(),
// check the response body does not contain "someString"
substring("someString").notExists()
)
.check(
// check the HTTP status is 200
status.is(200),
// check the HTTP status is in [200, 210]
status.in(200 to 210),
// check the response body contains 5 https links
regex("https://(.*)").count.is(5),
// check the response body contains 2 https links,
// the first one to www.google.com and the second one to gatling.io
regex("https://(.*)/.*").findAll.is(Seq("www.google.com", "gatling.io")),
// check the response body contains a second occurrence of "someString"
substring("someString").find(1).exists,
// check the response body does not contain "someString"
substring("someString").notExists
)