53JMeter (load testing classic)
What you will master here
- JMeter mental model: test plan, thread group, sampler, listener
- Load profiles: ramp-up, steady, soak, spike
- Recording with the proxy + HAR import
- Assertions, correlations, parameterisation (CSV Data Set)
- Distributed runs, non-GUI mode
- Reading the result (throughput, latency percentiles, error rate)
- JMeter vs k6 vs Gatling vs Locust — when to pick which
53.1 Mental model
| Element | What it is |
|---|---|
| Test Plan | Top-level container; one .jmx file |
| Thread Group | Virtual users (threads) + ramp-up + iterations |
| Sampler | The actual request (HTTP, JDBC, JMS, FTP) |
| Logic Controller | Loops, ifs, transactions |
| Listener | Collects/displays results |
| Assertion | Validate response (status, regex) |
| Config element | Defaults, cookies, headers, CSV data |
| Pre/Post processor | Run before/after a sampler (extract values, sleep) |
| Timer | Pause between requests |
53.2 First test plan
jmeter # GUI mode (only for editing, never for execution) jmeter -n -t plan.jmx -l results.jtl -e -o html-report # CLI (use this for real runs)
53.3 Load profile shapes
| Shape | Pattern | Use |
|---|---|---|
| Ramp-up | 0 → N users over T seconds | Find where it starts to break |
| Steady-state | N users for T minutes | Verify SLA under expected load |
| Spike | Sudden jump from low to high | Black Friday traffic spike |
| Soak | Moderate load for hours | Detect memory leaks, slow degradation |
| Stress | Ramp until break | Find absolute limit |
53.4 Recording via JMeter Proxy
- Add HTTP(S) Test Script Recorder.
- Configure browser to use JMeter as proxy (port 8888).
- Click through the app — JMeter records the requests as samplers.
- Clean up: remove asset requests (images, analytics), add timers, parameterise inputs.
53.5 Data-driven via CSV
# users.csv
email,password
alice@test.com,secret1
bob@test.com,secret2
# In JMeter: add "CSV Data Set Config" → filename users.csv, variables email,password
# In HTTP sampler: body = {"email": "${email}", "password": "${password}"}
# Each iteration reads the next row.
53.6 Correlations — extracting + reusing
The response of one request often contains a token/id the next request needs. Use a post-processor:
- JSON Extractor — JSONPath into a variable
- Regular Expression Extractor — for HTML / non-JSON
- Boundary Extractor — fast string-between approach
# JSON Extractor: $.access_token → token
# Next sampler header: Authorization: Bearer ${token}
53.7 Assertions
- Response Assertion — status code, contains string, doesn't contain, regex
- JSON Assertion — validate JSONPath value
- Duration Assertion — fail if request > N ms
- Size Assertion — response body within size range
53.8 Distributed run (master + slaves)
# On slave machines (default port 1099) jmeter-server # On master jmeter -n -t plan.jmx -R slave1,slave2,slave3 -l results.jtl # Or use Docker/k8s for ephemeral clusters
53.9 Reading results
| Metric | What it tells you |
|---|---|
| Throughput (req/s) | Capacity |
| Average / Median (p50) | Typical latency |
| p95 / p99 | Worst experience the bulk/edge users see |
| Min / Max | Outliers — look at why |
| Error % | How many requests failed |
| Aggregate Report / Summary Report | Standard tabular view |
Average liesA handful of 30-second responses can hide behind a "200 ms average". Always quote p95/p99, not average.
53.10 JMeter vs k6 vs Gatling vs Locust
| Tool | Lang | Style | Strengths |
|---|---|---|---|
| JMeter | Java / XML | GUI-first, samplers | Mature, plugins for everything (JMS, JDBC, MQTT) |
| k6 | JS (Go-powered) | Code-first | Modern DX, easy CI integration, great reports |
| Gatling | Scala / Java DSL | Code-first DSL | High throughput per host, beautiful HTML reports |
| Locust | Python | Code-first | Python familiarity, distributed easily |
Module 54 — JMeter Q&A
Why never run JMeter in GUI mode for actual tests?
GUI consumes huge CPU/memory rendering the listeners. It distorts measurements and limits the load you can generate from one machine. Use GUI only to author plans; run via
jmeter -n.What's a Thread Group?
JMeter's representation of virtual users. You set number of threads (users), ramp-up time, and iterations. All samplers under it execute per thread.
How do you parameterise inputs?
CSV Data Set Config — point to a CSV, declare variable names, reference as
${name} in samplers. Each iteration reads the next row.What's a correlation in load testing?
Extracting a dynamic value from one response and passing it into a subsequent request. Required for any flow with tokens, session ids, CSRF tokens. JMeter has JSON/Regex/Boundary extractors.
Average vs p95 — which matters more?
p95 (and p99). Average can hide a long tail — a few slow requests barely move the average but ruin a user's experience. SLA targets are usually p95 or p99.
How do you scale JMeter beyond one machine?
Distributed run: start
jmeter-server on N machines, run master with -R slave1,slave2,.... Master aggregates results. For ephemeral runs, use Docker images + Kubernetes Job.What is soak testing?
Sustained moderate load over hours. Catches memory leaks, slow performance degradation, connection-pool exhaustion. Not about peak — about endurance.
JMeter vs k6 in a modern SDET stack?
k6 fits CI/CD naturally (JS code in git, simple invocation, native dashboards). JMeter wins when you need protocols beyond HTTP (JDBC, JMS, MQTT, LDAP) or have legacy plans. For new web load tests, k6 usually wins.
How do you simulate think time between requests?
Use a Timer (Constant Timer, Gaussian Random Timer). Add as child of a sampler — applies before that sampler runs. Models real user pacing instead of hammering as fast as possible.
What does ramp-up time control?
Time to spawn all the threads. 100 threads with 10-second ramp-up means 10 threads/second. Avoids slamming the system at t=0 (unrealistic for most workloads).