before & after Expressions — Complete Examples
before and after are lifecycle hooks: ordered lists of expressions run for their side-effects (usually $find(..., variable=x) or the declarative methods with variable=).
beforeruns before an iteration's/request'sskipIf, URL, and headers — a pre‑execution hook for preparing data.afterruns after the iteration/request executes — a post‑execution hook, so it can read the response and captured variables and prepare data for the next step.
When after runs
- Request-level: after the request finishes (including its retries). It runs on both success and failure, but not when
skipIfskipped the request, and not on cancellation. - Iteration-level: after the iteration completes successfully.
All examples capture the public jsonplaceholder users array first, then use before/after.
Iteration-level before, then verify with skipIf
Two finds run in order at the start of the iteration; skipIf then verifies the result.
name: BeforeDemo
rounds:
- name: FeatureRound
numberOfClients: 3
arrivalDelay: 1000
runInParallel: false
iterations:
- name: getUsers
httpRequest:
capture:
to: users
as: Json
makeGlobal: true
url: https://jsonplaceholder.typicode.com/users
method: GET
- name: useMatchedUser
before:
- '$find(source=$users.Body, where=item.company.name == "Romaguera-Crona", match=first, variable=matchedUser)'
- '$find(source=$users.Body, where=item.username == "Bret", select=item.id, match=first, variable=uid)'
# skipIf skips when TRUE, so this runs only when the match is who we expect.
skipIf: '${uid} != 1 or "${matchedUser.username}" != "Bret"'
httpRequest:
url: 'https://jsonplaceholder.typicode.com/users/${matchedUser.id}/todos'
method: GET
Request-level before
The setup runs right before this specific request is sent.
name: BeforeRequestDemo
rounds:
- name: FeatureRound
numberOfClients: 1
arrivalDelay: 1000
runInParallel: false
iterations:
- name: getUsers
httpRequest:
capture:
to: users
as: Json
makeGlobal: true
url: https://jsonplaceholder.typicode.com/users
method: GET
- name: getAlbums
httpRequest:
before:
- '$find(source=$users.Body, where=item.username == "Bret", select=item.id, match=first, variable=userId)'
url: 'https://jsonplaceholder.typicode.com/users/${userId}/albums'
method: GET
Several expressions in order
before is a list; expressions run top to bottom, and a later one can use what an earlier one stored.
name: BeforeChainDemo
rounds:
- name: FeatureRound
numberOfClients: 1
arrivalDelay: 1000
runInParallel: false
iterations:
- name: getUsers
httpRequest:
capture:
to: users
as: Json
makeGlobal: true
url: https://jsonplaceholder.typicode.com/users
method: GET
- name: doWork
before:
- '$find(source=$users.Body, where=item.username == "Bret", select=item.id, match=first, variable=userId)'
- '$find(source=$users.Body, where=item.username == "Bret", select=item.company.name, match=first, variable=companyName)'
- '$find(source=$users.Body, where=item.id > 5, match=count, variable=bigUserCount)'
httpRequest:
headers:
X-Company: '${companyName}'
X-Big-Users: '${bigUserCount}'
url: 'https://jsonplaceholder.typicode.com/users/${userId}/albums'
method: GET
after: post-execution hook (request-level)
after runs once the request has completed and its response is captured, so it can extract data from this response for a later step. Here it captures the user, then after pulls a field out of the response body.
name: AfterRequestDemo
rounds:
- name: FeatureRound
numberOfClients: 1
arrivalDelay: 1000
runInParallel: false
iterations:
- name: getUser
httpRequest:
capture:
to: user
as: Json
makeGlobal: true
url: https://jsonplaceholder.typicode.com/users/1
method: GET
after:
- '$setvariable(variable=userCity, value=${user.Body.address.city})'
- '$find(source=$user.Body.address, where=item.zipcode != "", select=item.zipcode, match=first, variable=userZip)'
- name: useAfterResults
httpRequest:
headers:
X-User-City: '${userCity}'
X-User-Zip: '${userZip}'
url: https://jsonplaceholder.typicode.com/posts/1
method: GET
after: post-execution hook (iteration-level)
Iteration-level after runs after the iteration completes successfully. Use it to compute roll-up values from what the iteration produced.
name: AfterIterationDemo
rounds:
- name: FeatureRound
numberOfClients: 1
arrivalDelay: 1000
runInParallel: false
iterations:
- name: getUsers
after:
- '$find(source=$users.Body, where=item.id > 5, match=count, variable=bigUserCount)'
- '$greaterthan(a=${bigUserCount}, b=3, variable=hasManyUsers)'
httpRequest:
capture:
to: users
as: Json
makeGlobal: true
url: https://jsonplaceholder.typicode.com/users
method: GET
before + after together
before prepares inputs, the request runs, then after post-processes the response — a full pre/post pipeline around a single request.
name: BeforeAfterDemo
rounds:
- name: FeatureRound
numberOfClients: 1
arrivalDelay: 1000
runInParallel: false
iterations:
- name: getUsers
httpRequest:
capture:
to: users
as: Json
makeGlobal: true
url: https://jsonplaceholder.typicode.com/users
method: GET
- name: process
httpRequest:
before:
- '$find(source=$users.Body, where=item.username == "Bret", select=item.id, match=first, variable=userId)'
capture:
to: todos
as: Json
makeGlobal: true
url: 'https://jsonplaceholder.typicode.com/users/${userId}/todos'
method: GET
after:
- '$find(source=$todos.Body, where=item.completed == true, match=count, variable=completedCount)'
- '$find(source=$todos.Body, match=count, variable=totalCount)'
- '$divide(a=${completedCount}, b=${totalCount}, variable=completionRatio)'