Chapter 03Lesson 05~170 minutes

Checkpoint Lab — Test Plan Tree, Scope, Execution Order, and Component Semantics

Complete the chapter by proving tree semantics rather than memorizing them. Build a two-request loopback plan, predict scope and execution order, capture variables in one bounded Debug Sampler run, deliberately mis-scope the header, diagnose Beta's planned assertion failure, restore the tree, and retain before/broken/after evidence.

CheckpointScope mapControlled failureJTLTree diff

Learning objectives

  • Construct and annotate a multi-request tree with explicit scope.
  • Predict sampler order and applicable component phases before running.
  • Use Debug Sampler/View Results Tree only for a bounded variable-inspection pass.
  • Run lean CLI copies with unique JTL and jmeter.log.
  • Introduce one reversible Header Manager mis-scope and diagnose resulting assertion evidence.
  • Restore the tree and state what the experiment proves and does not prove.

1. Scenario, assumptions, and ceiling

Item Checkpoint baseline
JMeter Apache JMeter 5.6.3.
Java Java 17 JDK lab baseline; 5.6.3 itself requires Java 8+.
Plugins None.
Target http://127.0.0.1:8000 only.
Threads / loops 1 thread × 1 loop.
Network samplers Alpha then Beta; exactly 2 target requests per run.
Broad elements Header Manager, 150 ms Timer, Response Assertion, Regular Expression Extractor under Scope Lab.
Diagnostics Debug Sampler + View Results Tree only in debug copy.
Load evidence CLI copy with diagnostics disabled.
Abort criteria: stop if target is not loopback, fixture is unhealthy, request count exceeds two, unexpected failures occur outside the deliberate broken run, or generator state becomes unsafe. Do not increase load.

2. Create a clean checkpoint workspace

jmeter-ch03-checkpoint/
├── fixtures/scope_fixture.py
├── plans/
│   ├── 01-broad-debug.jmx
│   ├── 01-broad-load.jmx
│   ├── 02-header-broken-debug.jmx
│   ├── 02-header-broken-load.jmx
│   ├── 03-restored-debug.jmx
│   └── 03-restored-load.jmx
├── evidence/
│   ├── scope-map.txt
│   ├── predictions.txt
│   └── tree-diff.txt
└── results/

Save the Lesson 2 fixture as fixtures/scope_fixture.py and start it separately.

3. Build and save the intended broad tree

Test Plan
└── Thread Group — 1 thread, 1 loop
    ├── HTTP Request Defaults — http / 127.0.0.1 / 8000
    ├── Simple Controller — Scope Lab
    │   ├── HTTP Header Manager — X-Lab-Scope: broad
    │   ├── Constant Timer — 150 ms
    │   ├── Response Assertion — body contains "scope_header": "broad"
    │   ├── Regular Expression Extractor
    │   │   └── last_request_id <- "request_id":\s*(\d+)
    │   ├── HTTP Request — Alpha — GET /alpha
    │   └── HTTP Request — Beta  — GET /beta
    ├── Debug Sampler — Inspect variables after Scope Lab
    └── View Results Tree — AUTHORING DEBUG ONLY

Save 01-broad-debug.jmx. Duplicate it as 01-broad-load.jmx and disable Debug Sampler/View Results Tree in the load copy.

4. Write the scope map before execution

Sampler Header Timer Post-Processor Assertion Observation
Alpha broad 150 ms before extract Alpha request_id expects broad Debug/JTL.
Beta broad 150 ms before extract Beta request_id expects broad Debug/JTL.
Debug Sampler outside Scope Lab outside outside outside Reads thread variables only.

Expected applicable sequence for Alpha/Beta is configuration → timer → HTTP sampler → extractor → assertion → listener. There is no Pre-Processor in this checkpoint.

5. Write predictions before baseline

  1. Target receives Alpha then Beta: two requests total.
  2. Both responses echo scope_header=broad.
  3. Both assertions pass.
  4. Broad extractor runs after each; after Beta, last_request_id equals Beta's ID.
  5. Broad timer delays both request starts; sampler elapsed remains dominated by fixture response time.

6. Bounded Debug Sampler verification

Start a fresh fixture and run 01-broad-debug.jmx once in GUI. Confirm Alpha/Beta response bodies, both green assertions, Debug Sampler last_request_id, and capture a tree screenshot/text export. Restart the fixture before CLI evidence.

7. Baseline CLI evidence run

mkdir -p results/01-broad
jmeter -n -t plans/01-broad-load.jmx \
  -l results/01-broad/results.jtl \
  -j results/01-broad/jmeter.log
New-Item -ItemType Directory -Force results\01-broad | Out-Null
jmeter.bat -n `
  -t plans\01-broad-load.jmx `
  -l results\01-broad\results.jtl `
  -j results\01-broad\jmeter.log

Verify fixture total 2 (Alpha 1, Beta 1), two network JTL rows, and zero failed samples.

8. Deliberately mis-scope one element

Copy broad debug plan to 02-header-broken-debug.jmx. Move only Header Manager under Alpha; leave Response Assertion broad.

  • Alpha still passes with broad header.
  • Beta reaches target without X-Lab-Scope.
  • Beta response is valid JSON with scope_header=<missing>.
  • Beta fails only because broad assertion still requires broad.
  • Broad extractor still runs after Beta, so Debug Sampler still shows Beta request ID.

9. Verify broken tree without hiding the failure

Restart fixture and run broken debug plan once. Preserve tree image/text, Alpha/Beta bodies, Beta assertion failure, Debug variable, and fixture stats. This is a planned scope/correctness failure, not target availability failure.

10. Run broken state through CLI

Create the load copy by disabling Debug Sampler/View Results Tree, restart fixture, and run:

mkdir -p results/02-header-broken
jmeter -n -t plans/02-header-broken-load.jmx \
  -l results/02-header-broken/results.jtl \
  -j results/02-header-broken/jmeter.log

Expected: Alpha succeeds, Beta is failed by assertion, fixture still reports two requests. Preserve the failed JTL.

11. Diagnose by tree semantics

Evidence Observation Conclusion
Fixture stats Alpha 1, Beta 1 Network execution order/count unchanged.
Alpha response scope_header=broad Narrow Header Manager applies to Alpha.
Beta response scope_header=<missing> Header Manager no longer applies to Beta.
Beta assertion Failed Broad assertion still applies.
Debug variable Beta request ID Extractor remains broad.
jmeter.log No engine-startup problem expected Fault is tree correctness, not toolchain startup.

Given original intent that both requests require the header, the smallest correction is restoring Header Manager to Scope Lab.

12. Restore, rerun, compare

Copy broken plan to 03-restored-debug.jmx, move Header Manager back under Scope Lab, create load copy with diagnostics disabled, restart fixture, and run into results/03-restored. Expect two requests and two successful samples.

13. Timing evidence and validity

Use the Lesson 2 JTL analyzer on baseline/broken/restored files. The header move should change correctness, not configured timer or synthetic service delay. Do not claim a performance regression from tiny-run timing noise.

import csv
from pathlib import Path
path=Path('results/run-001/results.jtl')
rows=list(csv.DictReader(path.open(encoding='utf-8')))
print(f'samples={len(rows)}')
for r in rows:
    print(f"{r['label']}: success={r['success']} elapsed_ms={r['elapsed']} timestamp={r['timeStamp']}")
network=[r for r in rows if r['label'] in {'Alpha','Beta'}]
if len(network)==2:
    print('alpha_to_beta_start_gap_ms='+str(int(network[1]['timeStamp'])-int(network[0]['timeStamp'])))

14. Required evidence packet

Artifact Why it matters
Broad/broken/restored JMX Exact tree states.
Tree screenshots/text exports Human-reviewable scope placement.
Scope map + predictions Expectations existed before execution.
Bounded Debug Sampler variables Extractor/thread-variable lifecycle.
Three CLI JTLs Baseline, deliberate failure, restored raw evidence.
Three jmeter.log files Engine/runtime provenance.
Fixture stats Independent target request-count evidence.
Tree diff Shows one intended parent-scope change.
Validity note Prevents unsupported capacity claims.

15. Write the validity note

Example: “Using JMeter 5.6.3 with Java 17 against the loopback-only Chapter 03 fixture, moving Header Manager from controller scope to Alpha-only scope removed the header from Beta while leaving Beta network execution intact. Because Response Assertion remained broad, Beta became failed; restoring Header Manager restored the intended outcome. This demonstrates the tested JMeter scope relationship under this tree. It does not establish production capacity, distributed behavior, or a performance regression.”

16. Cleanup and rollback

  1. Stop the Python fixture.
  2. Keep before/broken/restored JMX and result evidence through review.
  3. Disable/remove authoring-only Debug Sampler/View Results Tree from the load profile that continues to Chapter 04.
  4. No production systems, credentials, certificates, databases, remote engines, containers, plugins, or system-wide settings were changed.

17. What Chapter 03 adds to the operating model

Chapter 01 defined experiment intent; Chapter 02 added toolchain provenance; Chapter 03 adds execution-architecture provenance. A reviewer can now trace each sampler through its ancestors and explain configuration, waits, extraction, assertions, and result observers.

Chapter 04 builds on this to design virtual users, ramp-up, loops, duration, and workload shape deliberately.

Knowledge check

In the broken checkpoint, why does Beta still reach the fixture?

Why is Beta failed even though server returns HTTP 200?

What proves the extractor remained broad?

Why retain the broken JTL after restored run passes?

What is the bridge to Chapter 04?

Next chapter

Thread Groups, Virtual Users, Ramp-Up, Loops, and Workload Modeling

You now know what each thread executes. Chapter 04 turns that execution unit into a deliberate concurrency/workload model and separates configured schedules from achieved request/iteration rates.

Official references and version notes

  • Elements of a Test Plan — execution order, scoping rules, variables/properties, timers, assertions, configuration elements, processors, listeners, controllers, and samplers.
  • Component Reference — Header Manager, Constant Timer, Response Assertion, Regular Expression Extractor, Debug Sampler, Transaction Controller, and listeners.
  • Functions and Variables — sampler-context functions and variable semantics.
  • Hints and Tips — current quick-add bindings for common debug elements.
  • Getting Started and Best Practices — GUI authoring versus CLI load execution and lean result collection.
  • Apache JMeter downloads — current production release and Java requirement.
Version and compatibility note

Version-sensitive statements were rechecked against current Apache JMeter primary documentation on 2026-09-04. The baseline is Apache JMeter 5.6.3 with a Java 17 JDK for labs and no third-party plugins; JMeter 5.6.3 itself requires Java 8+. The current Test Plan manual defines applicable execution order as Configuration Elements → Pre-Processors → Timers → Sampler → Post-Processors → Assertions → Listeners. Controllers and samplers are primarily ordered; listeners, configuration elements, pre/post-processors, assertions, and timers are hierarchical/scoped. Mandatory traffic is restricted to http://127.0.0.1:8000, one thread and one loop. Debug Sampler/View Results Tree are bounded GUI diagnostics only; CLI remains the load-evidence path.

Keep the academy open

Support free, practical DevOps education.

Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0 Send only Ethereum/ERC-20 compatible assets to this address.