skip to content

Before a JMeter load run, how would you prove its green samples are real responses?

level: seniorimportance: should knowfreq 53%

answer

  1. Look at the response, not the icon
  2. One thread is enough to see it
  3. A sampler that prints the variables
  4. Take the scaffolding out afterwards

basics

~20 s

Run the plan once at one thread with a View Results Tree attached and read the Response data tab of every sample. Add a Debug Sampler after each extractor to see what the variables actually hold.

solid answer

~40 s

Use JMeter's own debugging surface first, then strip it out. Right-click the Thread Group and choose **Validate**: by default that clones the plan with one thread, one iteration, timers ignored and startup delay zeroed — the defaults live in `testplan_validation.nb_threads_per_thread_group`, `testplan_validation.number_iterations`, `testplan_validation.ignore_timers` and `testplan_validation.ignore_backends`. Attach a **View Results Tree** and read the *Response data* tab of each sample rather than trusting the green icon, because an error page is green there too. After every extractor add a **Debug Sampler** with *JMeter variables* ticked; its response data lists the thread's variables, so you can see whether `authToken` holds a real token or an extractor's Default Value. Then remove both before the load run.

code

text · 7 lines
text
JMeterVariables:
JMeterThread.last_sample_ok=true
START.HMS=101500
START.MS=1788948900123
START.YMD=20260909
TESTSTART.MS=1788948900456
authToken=NOT_FOUND

go deeper

for a junior

Learn to click a sample in the View Results Tree and read its Response data tab. The green icon only reports the status code, so it cannot tell you the page was the one you wanted.

for a middle

Explain what Validate does to the cloned plan and what a Debug Sampler dumps, and know that the sampler itself always records a successful 200 row of its own.

for a senior

Build the pre-flight into how you ship a plan: validate small, read every distinct response body, check the variables, then convert what you saw into assertions and remove the debugging elements.

for a principal

Make the pre-flight a condition of a plan being usable rather than a personal habit, so that no run reaches a report without someone having read the responses it is built on.

A green tree is not evidence. The icon in a View Results Tree is painted from `sampleResult.isSuccessful()`, and with no assertion in the plan that flag means only that the status code landed between 200 and 399. Proving the samples are real is a separate, deliberate step, and it is cheap if you do it before the load run rather than after. ## Run the plan small, on purpose Right-clicking a Thread Group offers **Validate**. It clones the plan through `ComponentTreeClonerForValidation` and runs it under a set of overrides that `jmeter.properties` documents: - `testplan_validation.nb_threads_per_thread_group=1` - `testplan_validation.number_iterations=1` - `testplan_validation.ignore_timers=true` - `testplan_validation.ignore_backends=true` One thread, one iteration, no waiting, and no Backend Listener firing at your metrics store. That is exactly the shape you want for reading every response by hand, and it is a different activity from the load run — which is why the heavyweight listeners you are about to attach are acceptable here and not there. ## Read the response, not the icon Select a sample in the **View Results Tree** and use the three tabs deliberately: | Tab | What it settles | |---|---| | Sampler result | the response code and message, sizes, latency, and whether an assertion fired | | Request | what JMeter actually sent, including any `${...}` reference that never resolved | | Response data | the body — the only place an error page announces itself | The renderer dropdown at the top of the left-hand panel, above the sample tree, switches between Text, HTML, JSON and the other views, which matters when the error page is a full HTML document and the real reply is JSON. The habit to build is: for each distinct sampler in the plan, look at the response body once, and confirm it is the document you meant to fetch. ## Make the variables visible The second half of a false green lives in the variables, not the responses. Put a **Debug Sampler** immediately after each extractor. It is a real sampler — it always records response code `200`, message `OK` and success `true` — whose response data is a dump of the thread's state. Its three checkboxes are *JMeter variables* (ticked by default), *JMeter properties* and *System properties*; for this job you want the first only, because the other two dump JVM-wide values and bury the four lines you care about. What you are looking for in that dump: 1. **The variable is present and holds a plausible value.** A token, an id, a cart number. 2. **The variable is present and holds the extractor's Default Value.** The extraction missed and the plan is about to send a placeholder. 3. **The variable is absent entirely.** The extractor wrote nothing, and every `${...}` reference to it will render as its own text. Every thread also carries `JMeterThread.last_sample_ok` and the four preloaded entries `START.MS`, `START.YMD`, `START.HMS` and `TESTSTART.MS`, so a Debug Sampler dump is never empty even when your own extraction produced nothing — do not read a populated list as proof that your variable is in it. ## Then take the scaffolding out Both elements are debugging tools and both cost you at load. The component reference is explicit that the View Results Tree must not be used during a load test, and a Debug Sampler adds a green row to the results file for every iteration, inflating the sample count and diluting the error percentage of the run you are about to publish. Disable or delete them before the real run. ## What survives into the load run The point of the exercise is to convert what you saw into something that keeps checking when nobody is watching: - a **Response Assertion** on each sampler that matters, testing a string only a genuine reply carries - a distinctive **Default Value** on each extractor, so a missed capture is recognisable in a report rather than plausible - a note of which samplers legitimately expect a non-2xx reply, so nobody later ticks Ignore Status across the plan to quiet them That is the difference between a JMeter run whose Err line means the service worked and one whose Err line means only that the service answered inside 200 to 399.

  • What does the Thread Group's Validate action change about how the plan runs?
    It clones the plan and runs it with one thread and one iteration, with timers and Backend Listeners ignored and any startup delay set to zero. The values come from `testplan_validation.nb_threads_per_thread_group`, `number_iterations`, `ignore_timers` and `ignore_backends` in `jmeter.properties`, all overridable.
  • Which Debug Sampler checkbox is on by default, and what do the other two add?
    *JMeter variables* is on by default; *JMeter properties* and *System properties* are off. The variables list is what a false-green hunt needs, because it is per-thread and shows the extractor's output. The other two dump values shared across the whole JVM and make the response very long.

saying these in an interview costs you the question

  • Trusts the green icon in the results tree
  • Debugs a false green at full thread count
  • Checks only the run's summary error count
  • Thinks the Debug Sampler prints the previous response
  • Leaves the debugging elements in the load run