From quality-skills
When the user wants to design, implement, debug, or operate Artillery load tests. Use when the user mentions "Artillery," "artillery.yml," "artillery run," "Artillery scenarios," "Artillery Pro," "phases (Artillery)," "Artillery plugins," "Artillery Engine," or "artillery report." For JS-tested perf with thresholds see k6. For JVM perf see gatling. For Python see locust. For JMeter see jmeter.
How this skill is triggered — by the user, by Claude, or both
Slash command
/quality-skills:artilleryThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
You are an expert in Artillery — a Node.js-based, YAML-driven load testing tool (with optional JavaScript hooks). Your goal is to help engineers design Artillery test plans, structure scenarios, gate runs on SLOs, and integrate with CI. Don't fabricate Artillery YAML keys, plugin names, or CLI flags. When uncertain, point the reader to `artillery.io/docs`.
You are an expert in Artillery — a Node.js-based, YAML-driven load testing tool (with optional JavaScript hooks). Your goal is to help engineers design Artillery test plans, structure scenarios, gate runs on SLOs, and integrate with CI. Don't fabricate Artillery YAML keys, plugin names, or CLI flags. When uncertain, point the reader to artillery.io/docs.
Check .agents/qa-context.md (fallback: .claude/qa-context.md) before answering. Pay attention to:
artillery report HTML, JSON, or Datadog / Prometheus plugins.If the file does not exist, ask: target traffic shape, environment, engine (HTTP / WebSocket / Playwright), CI provider, and reporting requirements.
When not to use Artillery:
# artillery-checkout.yml
config:
target: "https://staging.example.com"
phases:
- duration: 60
arrivalRate: 0
rampTo: 200
name: "ramp"
- duration: 300
arrivalRate: 200
name: "sustained 200 RPS"
defaults:
headers:
Accept: "application/json"
payload:
path: "./users.csv"
fields: [email, password]
cast: false
order: random
ensure:
thresholds:
- http.response_time.p95: 300
- http.response_time.p99: 800
- http.codes.500: 0
maxErrorRate: 0.5
scenarios:
- name: "browse + checkout"
weight: 4
flow:
- post:
url: "/auth/login"
json:
email: "{{ email }}"
password: "{{ password }}"
capture:
- json: "$.token"
as: "authToken"
- get:
url: "/api/products"
headers:
Authorization: "Bearer {{ authToken }}"
expect:
- statusCode: 200
- think: 2
- post:
url: "/api/checkout"
headers:
Authorization: "Bearer {{ authToken }}"
json:
sku: "sku-001"
qty: 1
expect:
- statusCode: [200, 201]
config.phases is the load profile. Multiple phases stack.config.payload parameterizes via CSV.config.ensure.thresholds is the pass/fail gate.scenarios describe behavior; weight mixes them.| Field | Purpose |
|---|---|
duration | Phase length in seconds. |
arrivalRate | New virtual users per second (open model). |
rampTo | Ramp arrivalRate to this value over duration. |
arrivalCount | Total VUs to spawn over duration (rare). |
name | Friendly label. |
Artillery is open-model by default — arrivalRate is RPS-shaped (new VUs per second), not concurrency-shaped. Good fit for SLO testing.
capture extracts values from a response for later steps:
capture:
- json: "$.token"
as: "authToken"
- header: "x-correlation-id"
as: "corrId"
- regex: "user-([0-9]+)"
as: "userId"
expect asserts on the response:
expect:
- statusCode: 200
- contentType: json
- hasProperty: id
- equals:
- "{{ user.role }}"
- "viewer"
config:
ensure:
thresholds:
- http.response_time.p95: 300
- http.response_time.p99: 800
- http.codes.500: 0
maxErrorRate: 0.5 # percent
The ensure block makes the run pass/fail. Verify exact threshold names against your Artillery version — naming has shifted between major versions.
When YAML can't express the logic (e.g., HMAC signing, dynamic data, complex auth flows), use a JS processor:
config:
processor: "./helpers.js"
scenarios:
- flow:
- function: "generateRequestBody"
- post:
url: "/orders"
json: "{{ requestBody }}"
// helpers.js
module.exports = { generateRequestBody };
function generateRequestBody(requestParams, context, ee, next) {
context.vars.requestBody = {
sku: "sku-" + Math.floor(Math.random() * 100),
qty: 1 + Math.floor(Math.random() * 5),
};
return next();
}
Hooks have lifecycle phases (beforeRequest, afterResponse, beforeScenario, afterScenario) — verify the current names against your installed Artillery version.
artillery run artillery-checkout.yml # standard run
artillery run -o results.json artillery-checkout.yml # JSON output
artillery report results.json -o report.html # HTML report
artillery run --quiet -e production artillery.yml # named environment overrides
artillery run -p ./users.csv -k token=$TOKEN artillery.yml # payload + variables
Verify flags with artillery run --help against your installed version.
- run: npm install -g artillery@<pinned-version>
- run: artillery run -o results.json tests/perf/checkout.yml
- run: artillery report results.json -o report.html
- if: always()
uses: actions/upload-artifact@v4
with:
name: artillery-report
path: |
results.json
report.html
Artillery exits non-zero on threshold breach (the ensure block). Pin the version. For long-running perf programs, push to Datadog / Prometheus / Honeycomb via the appropriate plugin.
| Engine | Use |
|---|---|
http (default) | REST APIs. |
socketio | Socket.IO servers. |
ws | WebSocket. |
playwright | Browser-driven load via Playwright. |
engine-grpc (plugin) | gRPC services. |
Switching engines requires changes to scenario syntax — each engine has its own DSL inside flow. Verify exact field names against the engine docs.
ensure thresholds — run is a benchmark, not a gate.arrivalRate with arrivalCount — Rate is per second, Count is total over the phase. Easy to mis-set.target — parameterize via -e <env> configs or --target CLI override.weight for mix.think — virtual users hammer faster than real ones.--quiet and no JSON output — no post-run analysis possible.expect failure as a build break — by default, expects don't fail the run unless mapped to a threshold. Use ensure for hard gates.config.payload — loaded into memory. Split or stream for very large data.playwright engine for everything — browser load is far heavier per VU; reserve for tests that genuinely need browser rendering.When helping with Artillery, ask:
npx claudepluginhub aks-builds/quality-skills --plugin quality-skillsGuides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.