skip to content

In JMeter, what does an XML Schema Assertion do on every sample that a Response Assertion does not?

level: seniorimportance: nice to knowfreq 33%

answer

  1. One family reads text, one builds a tree
  2. A new validating parser for every sample
  3. Only the compiled XPath is cached
  4. Cost tracks document size, not pattern size

basics

~20 s

It parses the whole response as an XML document and validates it against the schema file, building a fresh validating JAXP parser for each sample. A Response Assertion only walks the text. The parse is the expensive part.

solid answer

~50 s

`XMLSchemaAssertion` takes the response body as a string and, for **every** sample, creates a new `DocumentBuilderFactory`, switches on validation and namespace-awareness, points it at the file named in *File Name* through the JAXP schema-source property, builds a `DocumentBuilder` and parses the document. JMeter caches none of that between samples. The XPath2 Assertion is in the same family: it builds a Saxon `XdmNode` tree for the whole response on every sample, plus a throwaway DOM document used to resolve namespace prefixes; only the compiled XPath expression is cached, in a store sized by `xpath2query.parser.cache.size`, default 400. So the recurring cost of these assertions scales with the **size of the document**, not with the complexity of the pattern — the opposite of a `Substring` check, and a very different proposition when the element is attached to every sampler in a 500-thread plan.

code

xml · 3 lines
xml
<XMLSchemaAssertion guiclass="XMLSchemaAssertionGUI" testclass="XMLSchemaAssertion" testname="XML Schema Assertion" enabled="true">
  <stringProp name="xmlschema_assertion_filename">order-response.xsd</stringProp>
</XMLSchemaAssertion>

go deeper

for a junior

Know the category difference: some assertions read the response as text, and some parse it into a document first. The parsing ones cost far more per sample.

for a middle

Explain what is rebuilt per sample — a validating parser and the parsed document — and what is genuinely cached, which for the XPath2 Assertion is only the compiled expression.

for a senior

Judge whether structural validation belongs inside the load plan at all, and be able to state the cheaper alternatives and honestly what each one gives up.

for a principal

Decide where structural validation lives across the team's plans, and be explicit that JMeter offers no sampling rate and no off-thread evaluation, so the only lever is plan structure.

## Two different cost models It helps to sort JMeter's stock assertions by what they actually do to a response. | Assertion | Per-sample work | Cost scales with | |---|---|---| | Response Assertion, `Substring` | Literal scan of one field | Length of that field | | Response Assertion, `Contains` | Regex scan of one field | Field length and pattern shape | | Size Assertion | Compare a byte count | Nothing | | Duration Assertion | Compare an elapsed value | Nothing | | XML Assertion | Parse the body as XML | Document size | | XPath2 Assertion | Build a Saxon tree, then evaluate | Document size | | XML Schema Assertion | Build a validating parser, parse against the XSD | Document size and schema complexity | The first group reads text. The last group builds an in-memory representation of the entire document before it can answer anything. That is a step change, not a percentage. ## What XML Schema Assertion does per sample The element's whole configuration is one field, *File Name*, holding the path to an XSD. On each result it: 1. pulls the response body out as a string; 2. creates a **new** `DocumentBuilderFactory`; 3. sets `validating` and `namespaceAware` to true and enables secure processing; 4. sets the JAXP schema-language and schema-source attributes, the latter to the XSD file name; 5. builds a **new** `DocumentBuilder`, attaches an error handler that records failures onto the assertion result; 6. parses the whole document. Steps 2 to 5 are setup that a caching implementation would do once. JMeter does them for every sample, on every thread. There is no schema cache, no parser pool, and no option in the GUI to add one. ## What XPath2 Assertion does per sample The XPath2 Assertion is Saxon-based, and it splits cleanly into a cheap half and an expensive half: - **Cached:** the compiled XPath expression, keyed by query plus namespace declarations, in a cache sized by `xpath2query.parser.cache.size` (default 400). Write the same expression in a thousand plans and it compiles once per key. - **Not cached:** the document. Every sample gets a fresh Saxon `XdmNode` built from the whole response, and a separate throwaway DOM document created purely so the namespace prefixes in the expression can be resolved. The older XPath Assertion has its own version of the same trap, and the manual says so out loud: *"The non-tolerant parser can be quite slow, as it may need to download the DTD etc."* An assertion that can make a network call of its own, per sample, is not something to leave switched on in a 500-thread plan. ## The choice this leaves you When the response really is XML and the check really is structural, you have a small number of honest options: - **Narrow the field.** If the assertion only needs to see a status element, a `Substring` check against a distinctive literal in the body answers the same question without a parse. It is weaker, and you should say so rather than pretend otherwise. - **Move the check out of the load plan.** Run the schema validation in a small Thread Group with a handful of threads, or in a separate functional plan that is not trying to generate load, and keep the 500-thread group on cheap checks. - **Keep it and pay for it.** Sometimes structural validation is the point of the run. Then size the generator for it knowingly, and expect assertion CPU to be a first-class line item rather than a rounding error. The one option JMeter does not give you is a discount: there is no setting on any stock assertion that makes it run on only a share of samples, and no way to evaluate one off the sampler thread. ## A related expense worth naming The Response Assertion looks cheap, but one of its *Field to Test* options is not: `Document (text)` runs the response through Apache Tika's auto-detecting parser to extract plain text before any matching happens. That puts a plain Response Assertion squarely into the document-parsing family for as long as that radio is selected — with a default size ceiling of 10 MB per document, set by `document.max_size`. Selecting it by accident is an easy way to make a "simple text check" the most expensive element in the plan.

  • Which part of an XPath2 Assertion is cached between samples, and which part is not?
    The compiled XPath expression is cached, keyed by the query and its namespace declarations, in a store sized by `xpath2query.parser.cache.size` with a default of 400. The document is not: a Saxon node tree is built from the whole response for every sample, along with a throwaway DOM document used for prefix resolution.
  • Is there a Response Assertion setting that is as expensive as a document parse?
    Yes — setting *Field to Test* to `Document (text)`. That runs the response through Apache Tika's auto-detect parser to extract plain text before any matching happens, with a 10 MB default ceiling from `document.max_size`. The matching rule you chose is then irrelevant next to the extraction.

saying these in an interview costs you the question

  • Assumes JMeter caches the compiled schema between samples
  • Treats XML Schema Assertion as just another text check
  • Thinks a simpler XPath expression makes the parse cheaper
  • Leaves external DTD fetching on during a load run
  • Selects Document (text) for an ordinary string check