Key takeaways
- Without assertions a test passes on any response that is not a 4xx or 5xx, including an error page returned as 200.
- Assert on content as well as status, since a wrong body is still a failure.
- Keep assertions cheap. Heavy ones distort the timings you are measuring, and the Compare Assertion must not run in a load test.
What are assertions in JMeter?
An assertion is a check that compares an expected value with the actual value of a sample. In JMeter it is a test element that runs after a sampler and marks the sample as failed when the check does not hold. The failure then shows up in the error percentage of your reports, which is the point: without assertions JMeter only fails a sample on a connection error or an HTTP status in the 4xx or 5xx range.
Why use assertions in a load test?
Many load test scripts only look at the response status. That can make the final results wrong, because a 200 OK does not prove the application did its job. Typical cases:
- the application redirects to a maintenance page
- the application answers 200 OK but puts an error message in the body
- the application redirects to an error page and sends 200 OK with the reason in the text
An error page is usually small and fast, so these failures make your response times look better, not worse. Add assertions to GET/POST/PUT/PATCH requests, to API performance tests and to functional checks. If you are new to JMeter, start with the introduction to JMeter performance testing or the guide on load testing a web server with JMeter. k6 has the same blind spot, and its answer is checks combined with a threshold, as the guide to k6 checks shows.
Which assertions does JMeter support?
These are the assertion elements in the JMeter 5.6 component reference (checked against jmeter.apache.org, October 2026). The ones you will use most are first.
| Assertion | What it checks | Use in a load test? |
|---|---|---|
| Response Assertion | A pattern against the response body, code, message, headers, URL or request data | Yes |
| JSON Assertion | A JSONPath exists, optionally with an expected value | Yes |
| Duration Assertion | The response arrived within a given number of milliseconds | Yes |
| Size Assertion | The response size is equal to, greater than, less than or not equal to a byte count | Yes |
| JSR223 Assertion | Your own Groovy (or other JSR223) script decides pass or fail | Yes, keep the script short |
| XPath and XPath2 Assertion | An XPath expression matches in an XML or HTML document | Careful: the non-tolerant XPath parser can be slow |
| XML Assertion | The body is well-formed XML (no schema validation) | Careful with big bodies |
| XML Schema Assertion | The body validates against an XSD file | Mostly functional tests |
| HTML Assertion | The HTML syntax checked with JTidy | Mostly functional tests |
| Compare Assertion | Compares sample contents or times within its scope | No: the manual says it must not be used during a load test |
| MD5Hex, SMIME, JSON JMESPath, BeanShell | Hash check, signed mail check, JMESPath check, legacy script | Occasional. For scripts prefer JSR223 with Groovy over BeanShell |
Which scope do assertions apply to?
An assertion applies to every sampler in its scope, so its position in the tree matters. Put it under a sampler and it checks only that sampler. Put it under a controller or the thread group and it checks every sampler below. The JMeter manual’s example: assertion 1 under Request One applies to that request only, assertion 2 under a controller applies to Requests Two and Three. The three screenshots below show the same idea in the 2016 UI. For when assertions run relative to other elements, see the execution order of elements in JMeter.
1. applies to all the child requests

2. applies to all the sibling requests

3. applies only to one specific request

Samplers that produce sub-samples (an HTTP Request with embedded resources, a Transaction Controller) add a second question. The Response and Size assertions have an Apply to setting: Main sample only, Sub-samples only, Main sample and sub-samples, or a JMeter variable whose contents are tested.
How to use a Response Assertion in JMeter
The Response Assertion compares pattern strings against one field of the request or response. In the control panel you choose:
- Apply to: main sample, sub-samples, both, or a JMeter variable.
- Field to test: Text Response (the body), Request data, Response Code, Response Message, Response Headers (including Set-Cookie), Request Headers, URL sampled, or Document (text), which extracts text from files such as PDF and Word via Apache Tika.
- Pattern matching rules: Contains and Matches take Perl5-style regular expressions (Contains is true if the text contains the pattern, Matches only if the whole text matches). Equals and Substring are plain, case-sensitive strings. Not inverts the result and Or passes when any one pattern matches, where the default is that all patterns must match.
- Patterns to test: one or more patterns, entered without enclosing delimiters, so
Price: \d+, not/Price: \d+/. - Custom failure message: replaces the generated message in the results.
Two details cause most surprises. Patterns run in multi-line mode, so . does not match a newline and ^ and $ match at each line; prefix (?s) to let . cross lines and (?i) to ignore case. And the Ignore Status checkbox forces the sample to success before the assertion runs, which clears earlier assertion failures, so use it only on the first assertion.
Let’s start by adding a response assertion that expects the response code to be 200. The screenshot is from an old JMeter version (2.12); the 5.6 panel has the same fields plus a few more.

We will now add another assertion that expects the text “wikipedia” to be present in the response of the server.

Running the script shows that the request succeeded.

Now change the text of the second assertion to “dummy_text_inexistent” and run the test again. The sample fails.

How to use Duration, Size and JSON assertions
Duration Assertion. Set a maximum in milliseconds. Any response that takes longer is marked failed. Use it for a hard per-request limit; the percentile thresholds in your report remain the better tool for the overall picture.
Size Assertion. Compare the response size with a byte count using equal, greater than, less than or not equal. An empty response counts as 0 bytes rather than as an error, so a “greater than 0” check catches empty bodies.
JSON Assertion. It first parses the body and fails if it is not JSON. Then it looks up your JSONPath (Jayway JsonPath syntax) and fails if the path is not found. Optionally it compares the value, as an exact string or a regular expression, or expects null, and it can invert the result. If the path returns an array, the assertion passes when the expected value is found in it. Since JMeter 5.5 an indefinite path that extracts an empty list with no expected value set fails, instead of passing silently.
How to write a JSR223 Assertion with Groovy
When a check does not fit a built-in assertion, use the JSR223 Assertion with the language set to Groovy. The script gets prev (the previous SampleResult), vars, props, log and AssertionResult. To fail the sample, call AssertionResult.setFailure(true) and AssertionResult.setFailureMessage("..."). Tick Script compilation caching (the cache key box) so Groovy compiles the script once.
def body = new groovy.json.JsonSlurper().parseText(prev.getResponseDataAsString())
if (body.items.size() < 1) {
AssertionResult.setFailure(true)
AssertionResult.setFailureMessage("items list is empty")
}
I ran this against a local mock API with JMeter 5.6.3 in non-GUI mode. A response of {"status": "ok", "items": [1, 2, 3]} passed, and {"status": "error", "items": []} (also HTTP 200) failed with the message items list is empty in the results file. The same run showed that JMeter keeps only the first failure message per sample when several assertions fail, so do not expect a message from each. If your response is not JSON, prev.getResponseDataAsString() is the raw text to parse.
How do I see assertion results?
Add an Assertion Results listener (or View Results Tree) while you build the test. A failed assertion marks the sample failed, counts toward the error percentage in the Aggregate and Summary reports, and writes its message to the failureMessage column of the results file. For the real run, execute in non-GUI mode and read the results file, because GUI listeners cost memory and CPU.
How much do assertions cost in CPU and memory?
Plain pattern checks (Response, Duration, Size) work on data JMeter already holds, so they are the light option. The costly ones are those that parse or compare whole documents: the Compare Assertion (the manual says never in a load test), HTML Assertion (JTidy), XML Schema Assertion, and XPath Assertion when it uses the non-tolerant parser, which the manual calls quite slow. Keep long runs lean: one or two targeted assertions per request, a body-contains check on something specific, and no result-tree listeners. If you extract values from XML, the XPath Extractor how-to covers the extraction side.
You can also use LoadFocus to run your JMeter scripts, assertions included, from cloud locations with thousands of users.
Frequently Asked Questions
Why add assertions to a load test?
Without them the test passes on any response that is not a 4xx or 5xx. An error page returned with a 200 counts as a success, and the run reports excellent timings for failures.
What should I assert on?
Content as well as status. A response that returns the wrong body is still a failure, and it is exactly the kind that appears only under load. A short, specific string or JSONPath check is usually enough.
Can assertions affect the results?
Yes, if they are heavy. Document-level assertions consume load generator CPU and memory and distort the timings you are trying to measure, so keep them cheap and targeted.
What is the difference between Contains and Substring in a Response Assertion?
Contains and Matches use Perl5-style regular expressions. Substring and Equals are plain, case-sensitive strings. Use Substring when the text has regex characters such as dots or brackets and you want a literal match.
Should I use BeanShell or Groovy for a scripted assertion?
Groovy through the JSR223 Assertion. The JMeter manual recommends migrating from BeanShell to JSR223 with Groovy for performance and because BeanShell has limited maintenance.