perf-skills 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +8 -0
- package/README.md +227 -0
- package/package.json +42 -0
- package/perf-skills/.claude-plugin/plugin.json +5 -0
- package/perf-skills/SKILL.md +169 -0
- package/perf-skills/references/tools/gatling.md +286 -0
- package/perf-skills/references/tools/jmeter.md +251 -0
- package/perf-skills/references/tools/k6.md +269 -0
- package/perf-skills/references/tools/loadrunner.md +116 -0
- package/perf-skills/references/tools/locust.md +133 -0
- package/perf-skills/references/tools/neoload.md +61 -0
- package/perf-skills/references/tools/octoperf.md +50 -0
- package/perf-skills/references/topics/database-testing.md +214 -0
- package/perf-skills/references/topics/modern-architectures.md +314 -0
- package/perf-skills/references/topics/observability.md +201 -0
- package/perf-skills/references/topics/production-testing.md +214 -0
- package/perf-skills/references/topics/protocol-testing.md +274 -0
- package/perf-skills/references/topics/results-analysis.md +244 -0
- package/perf-skills/references/topics/script-generation.md +221 -0
- package/perf-skills/references/topics/test-data.md +196 -0
- package/perf-skills/references/topics/test-execution.md +281 -0
- package/perf-skills/references/topics/workload-design.md +207 -0
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
# k6 Reference
|
|
2
|
+
|
|
3
|
+
> Targets: k6 v0.50+, xk6 extensions ecosystem
|
|
4
|
+
|
|
5
|
+
k6 is a developer-centric, open-source load testing tool built by Grafana Labs. Tests are written in JavaScript/TypeScript and executed with a Go runtime — making it fast, scriptable, and CI/CD-friendly.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Core Concepts
|
|
10
|
+
|
|
11
|
+
| Concept | Description |
|
|
12
|
+
|---|---|
|
|
13
|
+
| **Virtual User (VU)** | A single simulated user executing the script |
|
|
14
|
+
| **Iteration** | One full execution of the default function |
|
|
15
|
+
| **Scenario** | Named execution profile with its own executor and config |
|
|
16
|
+
| **Executor** | Controls how VUs and iterations are scheduled |
|
|
17
|
+
| **Metric** | Built-in or custom measurement (counters, gauges, rates, trends) |
|
|
18
|
+
| **Check** | Inline assertion — does NOT fail the test; records pass/fail rate |
|
|
19
|
+
| **Threshold** | SLA definition — FAILS the test if breached |
|
|
20
|
+
| **Group** | Logical grouping of requests for metric aggregation |
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Script Structure
|
|
25
|
+
|
|
26
|
+
```javascript
|
|
27
|
+
import http from 'k6/http';
|
|
28
|
+
import { check, sleep, group } from 'k6';
|
|
29
|
+
import { Counter, Trend } from 'k6/metrics';
|
|
30
|
+
|
|
31
|
+
// Custom metrics
|
|
32
|
+
const loginErrors = new Counter('login_errors');
|
|
33
|
+
const checkoutDuration = new Trend('checkout_duration_ms');
|
|
34
|
+
|
|
35
|
+
// Test configuration
|
|
36
|
+
export const options = {
|
|
37
|
+
scenarios: {
|
|
38
|
+
ramp_up: {
|
|
39
|
+
executor: 'ramping-vus',
|
|
40
|
+
startVUs: 0,
|
|
41
|
+
stages: [
|
|
42
|
+
{ duration: '2m', target: 50 },
|
|
43
|
+
{ duration: '5m', target: 50 },
|
|
44
|
+
{ duration: '2m', target: 0 },
|
|
45
|
+
],
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
thresholds: {
|
|
49
|
+
http_req_duration: ['p(95)<500', 'p(99)<1000'],
|
|
50
|
+
http_req_failed: ['rate<0.01'],
|
|
51
|
+
login_errors: ['count<5'],
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
// Setup (runs once before VUs start)
|
|
56
|
+
export function setup() {
|
|
57
|
+
const res = http.post('https://api.example.com/auth/token', {
|
|
58
|
+
client_id: 'perf-test',
|
|
59
|
+
client_secret: __ENV.API_SECRET,
|
|
60
|
+
});
|
|
61
|
+
return { token: res.json('access_token') };
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Default VU function
|
|
65
|
+
export default function (data) {
|
|
66
|
+
group('Login Flow', () => {
|
|
67
|
+
const res = http.post('https://api.example.com/login', JSON.stringify({
|
|
68
|
+
username: `user_${__VU}@example.com`,
|
|
69
|
+
password: 'testpass',
|
|
70
|
+
}), {
|
|
71
|
+
headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${data.token}` },
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
const ok = check(res, {
|
|
75
|
+
'login status 200': (r) => r.status === 200,
|
|
76
|
+
'has userId': (r) => r.json('userId') !== undefined,
|
|
77
|
+
});
|
|
78
|
+
if (!ok) loginErrors.add(1);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
sleep(Math.random() * 3 + 1); // Think time: 1–4 seconds
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Teardown (runs once after all VUs finish)
|
|
85
|
+
export function teardown(data) {
|
|
86
|
+
// Cleanup, invalidate tokens, etc.
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Executors
|
|
93
|
+
|
|
94
|
+
| Executor | Use Case | Key Options |
|
|
95
|
+
|---|---|---|
|
|
96
|
+
| `ramping-vus` | Ramp up/down | `stages: [{duration, target}]` |
|
|
97
|
+
| `constant-vus` | Fixed concurrency | `vus`, `duration` |
|
|
98
|
+
| `per-vu-iterations` | Each VU runs N times | `vus`, `iterations` |
|
|
99
|
+
| `shared-iterations` | Total N iterations split across VUs | `vus`, `iterations` |
|
|
100
|
+
| `constant-arrival-rate` | Fixed RPS (open model) | `rate`, `duration`, `preAllocatedVUs` |
|
|
101
|
+
| `ramping-arrival-rate` | Ramping RPS (open model) | `stages`, `preAllocatedVUs` |
|
|
102
|
+
| `externally-controlled` | Controlled via k6 REST API in real-time | — |
|
|
103
|
+
|
|
104
|
+
> For closed vs open model guidance and when to use each, see `references/topics/workload-design.md`.
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Checks vs Thresholds
|
|
109
|
+
|
|
110
|
+
```javascript
|
|
111
|
+
// Check: logs pass/fail but does NOT fail the test
|
|
112
|
+
check(res, { 'status 200': (r) => r.status === 200 });
|
|
113
|
+
|
|
114
|
+
// Threshold: FAILS the test run (non-zero exit code) if breached
|
|
115
|
+
// Put these in options.thresholds
|
|
116
|
+
thresholds: {
|
|
117
|
+
http_req_duration: ['p(95)<500'], // p95 must be under 500ms
|
|
118
|
+
checks: ['rate>0.99'], // At least 99% of checks must pass
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Use thresholds for SLA enforcement in CI/CD pipelines.
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## Parameterization
|
|
127
|
+
|
|
128
|
+
### Environment variables
|
|
129
|
+
```bash
|
|
130
|
+
k6 run -e USERNAME=testuser -e PASSWORD=secret script.js
|
|
131
|
+
```
|
|
132
|
+
```javascript
|
|
133
|
+
const username = __ENV.USERNAME;
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### SharedArray (CSV / JSON data files)
|
|
137
|
+
```javascript
|
|
138
|
+
import { SharedArray } from 'k6/data';
|
|
139
|
+
import papaparse from 'https://jslib.k6.io/papaparse/5.1.1/index.js';
|
|
140
|
+
|
|
141
|
+
const users = new SharedArray('users', function () {
|
|
142
|
+
return papaparse.parse(open('./data/users.csv'), { header: true }).data;
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
export default function () {
|
|
146
|
+
const user = users[__VU % users.length]; // Round-robin by VU
|
|
147
|
+
// use user.username, user.password
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
**SharedArray loads data once and shares it across all VUs** — critical for memory efficiency at high concurrency.
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## Correlation (Session Handling)
|
|
156
|
+
|
|
157
|
+
```javascript
|
|
158
|
+
// Extract value from JSON response
|
|
159
|
+
const token = res.json('data.access_token');
|
|
160
|
+
|
|
161
|
+
// Extract from HTML (regex)
|
|
162
|
+
const csrfToken = res.html().find('input[name="_token"]').attr('value');
|
|
163
|
+
|
|
164
|
+
// Extract from headers
|
|
165
|
+
const sessionId = res.headers['Set-Cookie'].match(/JSESSIONID=([^;]+)/)[1];
|
|
166
|
+
|
|
167
|
+
// Use in next request
|
|
168
|
+
http.get('https://api.example.com/profile', {
|
|
169
|
+
headers: { 'Authorization': `Bearer ${token}` },
|
|
170
|
+
});
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## Custom Metrics
|
|
176
|
+
|
|
177
|
+
```javascript
|
|
178
|
+
import { Counter, Gauge, Rate, Trend } from 'k6/metrics';
|
|
179
|
+
|
|
180
|
+
const checkoutErrors = new Counter('checkout_errors'); // cumulative count
|
|
181
|
+
const activeUsers = new Gauge('active_users'); // current value
|
|
182
|
+
const successRate = new Rate('success_rate'); // ratio
|
|
183
|
+
const transactionTime = new Trend('transaction_time_ms'); // distribution (p50/p95/p99)
|
|
184
|
+
|
|
185
|
+
// Usage inside default()
|
|
186
|
+
transactionTime.add(res.timings.duration);
|
|
187
|
+
successRate.add(res.status === 200);
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## Modules & Extensions
|
|
193
|
+
|
|
194
|
+
### Built-in k6 modules
|
|
195
|
+
- `k6/http` — HTTP/1.1 and HTTP/2
|
|
196
|
+
- `k6/ws` — WebSocket
|
|
197
|
+
- `k6/grpc` — gRPC
|
|
198
|
+
- `k6/browser` — Browser-based testing (Chromium)
|
|
199
|
+
- `k6/experimental/redis` — Redis client
|
|
200
|
+
- `k6/crypto` — Hashing and HMAC
|
|
201
|
+
- `k6/encoding` — Base64
|
|
202
|
+
|
|
203
|
+
### Popular xk6 extensions (require custom build)
|
|
204
|
+
- `xk6-kafka` — Kafka load testing
|
|
205
|
+
- `xk6-sql` — SQL database testing
|
|
206
|
+
- `xk6-output-prometheus-remote` — Push metrics to Prometheus
|
|
207
|
+
|
|
208
|
+
Build custom k6: `xk6 build --with github.com/grafana/xk6-kafka`
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## Running k6
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
# Local run
|
|
216
|
+
k6 run script.js
|
|
217
|
+
|
|
218
|
+
# With options override
|
|
219
|
+
k6 run --vus 50 --duration 5m script.js
|
|
220
|
+
|
|
221
|
+
# With env vars
|
|
222
|
+
k6 run -e BASE_URL=https://staging.example.com script.js
|
|
223
|
+
|
|
224
|
+
# Output to multiple sinks
|
|
225
|
+
k6 run --out json=results.json --out influxdb=http://localhost:8086/k6 script.js
|
|
226
|
+
|
|
227
|
+
# Cloud run (Grafana Cloud k6)
|
|
228
|
+
k6 cloud script.js
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
## Output and Observability
|
|
234
|
+
|
|
235
|
+
| Output | Command |
|
|
236
|
+
|---|---|
|
|
237
|
+
| Terminal summary | Default |
|
|
238
|
+
| JSON | `--out json=results.json` |
|
|
239
|
+
| InfluxDB (Grafana stack) | `--out influxdb=http://influx:8086/k6` |
|
|
240
|
+
| Prometheus | `--out experimental-prometheus-rw` |
|
|
241
|
+
| Grafana Cloud | `k6 cloud` or `--out cloud` |
|
|
242
|
+
| CSV | `--out csv=results.csv` |
|
|
243
|
+
|
|
244
|
+
### InfluxDB + Grafana Dashboard
|
|
245
|
+
The canonical observability stack: k6 → InfluxDB → Grafana with the official k6 Grafana dashboard (ID: 2587).
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## TypeScript Support
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
# Use k6 template with TypeScript
|
|
253
|
+
npx create-k6-app@latest --template typescript my-test
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
Benefits: Type safety, IDE autocomplete, better refactoring for large test suites.
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
## k6-Specific Tips
|
|
261
|
+
|
|
262
|
+
- **Always use `SharedArray`** for data files — loading data inside `default()` causes massive per-iteration overhead.
|
|
263
|
+
- **Use `for` loops only for sequential steps**, not concurrency — use VUs and executors for parallel load.
|
|
264
|
+
- **Remove `console.log` from hot paths** — dramatically reduces throughput during load runs.
|
|
265
|
+
- **Use `__ENV.BASE_URL`** for environment portability — never hardcode base URLs.
|
|
266
|
+
- **Prefer thresholds over checks alone** — without thresholds, the test always "passes" in CI/CD.
|
|
267
|
+
|
|
268
|
+
> For CI/CD integration (GitHub Actions, GitLab CI, Jenkins), see `references/topics/test-execution.md`.
|
|
269
|
+
> For anti-patterns, assertions, think time, and parameterization principles, see **Key Principles** in `SKILL.md`.
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# LoadRunner Reference
|
|
2
|
+
|
|
3
|
+
> Targets: OpenText LoadRunner 2024+
|
|
4
|
+
|
|
5
|
+
HP/Micro Focus LoadRunner (now OpenText LoadRunner) is the industry-standard enterprise load testing tool, especially dominant in financial services, telecom, and government.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Core Components
|
|
10
|
+
|
|
11
|
+
| Component | Description |
|
|
12
|
+
|---|---|
|
|
13
|
+
| **VuGen** | Script recorder and editor (C-based scripting) |
|
|
14
|
+
| **Controller** | Orchestrates scenarios and load injection |
|
|
15
|
+
| **Load Generator** | Hosts running VUs |
|
|
16
|
+
| **Analysis** | Post-test results analysis and reporting |
|
|
17
|
+
| **LoadRunner Cloud** | SaaS cloud execution platform |
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## VuGen Script Structure
|
|
22
|
+
|
|
23
|
+
```c
|
|
24
|
+
// vuser_init: Runs once at startup
|
|
25
|
+
vuser_init()
|
|
26
|
+
{
|
|
27
|
+
lr_think_time(0);
|
|
28
|
+
web_set_user("testuser", "password", "realm");
|
|
29
|
+
return 0;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Action: Main loop (repeated per iteration)
|
|
33
|
+
Action()
|
|
34
|
+
{
|
|
35
|
+
// Parameterize
|
|
36
|
+
lr_start_transaction("Login");
|
|
37
|
+
web_submit_form("login",
|
|
38
|
+
ITEMDATA,
|
|
39
|
+
"Name=username", "Value={P_USERNAME}", ENDITEM,
|
|
40
|
+
"Name=password", "Value={P_PASSWORD}", ENDITEM,
|
|
41
|
+
LAST);
|
|
42
|
+
lr_end_transaction("Login", LR_AUTO);
|
|
43
|
+
|
|
44
|
+
lr_think_time(3);
|
|
45
|
+
|
|
46
|
+
// Correlate session ID
|
|
47
|
+
web_reg_save_param_regexp(
|
|
48
|
+
"ParamName=SessionToken",
|
|
49
|
+
"RegExp=name=\"_token\" value=\"([^\"]+)\"",
|
|
50
|
+
"Ord=1",
|
|
51
|
+
LAST);
|
|
52
|
+
web_url("Dashboard", "URL=https://app/dashboard", LAST);
|
|
53
|
+
|
|
54
|
+
return 0;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// vuser_end: Runs once at teardown
|
|
58
|
+
vuser_end()
|
|
59
|
+
{
|
|
60
|
+
web_custom_request("Logout", "URL=https://app/logout", "Method=POST", LAST);
|
|
61
|
+
return 0;
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Key Protocols
|
|
68
|
+
|
|
69
|
+
| Protocol | Use Case |
|
|
70
|
+
|---|---|
|
|
71
|
+
| Web (HTTP/HTML) | Standard web apps, REST APIs |
|
|
72
|
+
| Web Services | SOAP/WSDL |
|
|
73
|
+
| Citrix ICA | Virtual desktop (Citrix) |
|
|
74
|
+
| SAP GUI | SAP ERP client |
|
|
75
|
+
| Oracle NCA | Oracle Forms |
|
|
76
|
+
| TruClient | AJAX-heavy SPAs (browser-based recording) |
|
|
77
|
+
| JDBC | Database load testing |
|
|
78
|
+
| JMS | Message queue testing |
|
|
79
|
+
| Flex/AMF | Adobe Flex applications |
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Correlation in VuGen
|
|
84
|
+
|
|
85
|
+
```c
|
|
86
|
+
// Register extraction BEFORE the request it appears in
|
|
87
|
+
web_reg_save_param_regexp(
|
|
88
|
+
"ParamName=AuthToken",
|
|
89
|
+
"RegExp=Bearer ([A-Za-z0-9._-]+)",
|
|
90
|
+
"Search=Headers",
|
|
91
|
+
"Ord=1",
|
|
92
|
+
LAST);
|
|
93
|
+
|
|
94
|
+
// Use the parameter in subsequent requests
|
|
95
|
+
web_add_header("Authorization", "Bearer {AuthToken}");
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## Controller Scenario Design
|
|
101
|
+
|
|
102
|
+
1. **Manual Scenario** - specify VU count per script, ramp-up duration, load generator assignment.
|
|
103
|
+
2. **Goal-Oriented Scenario** - Controller adjusts VUs automatically to hit a target (RPS, response time).
|
|
104
|
+
3. **Percentage Mode** - define percentage of VU load for each script in a mixed workload.
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Analysis Tips
|
|
109
|
+
|
|
110
|
+
- Use **Transaction Response Time** breakdown (DNS, connect, send, wait, receive).
|
|
111
|
+
- Compare **Hits/sec** and **Throughput** against **Response Time** to find saturation points.
|
|
112
|
+
- Use **Correlation graphs** to overlay server metrics (CPU, memory) from SiteScope/Diagnostics.
|
|
113
|
+
- Export to Excel or integrate with LoadRunner Cloud for trend analysis across runs.
|
|
114
|
+
|
|
115
|
+
> For anti-patterns, assertions, think time, and parameterization principles, see **Key Principles** in `SKILL.md`.
|
|
116
|
+
> For CI/CD integration details, see `references/topics/test-execution.md`.
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# Locust Reference
|
|
2
|
+
|
|
3
|
+
> Targets: Locust 2.20+, Python 3.9+
|
|
4
|
+
|
|
5
|
+
Locust is a Python-based, open-source load testing tool. Tests are plain Python code — no DSL, no XML. It supports distributed testing and has a built-in web UI.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Core Concepts
|
|
10
|
+
|
|
11
|
+
| Concept | Description |
|
|
12
|
+
|---|---|
|
|
13
|
+
| **User class** | Defines behavior of a simulated user |
|
|
14
|
+
| **TaskSet** | Group of tasks; can be nested |
|
|
15
|
+
| **task decorator** | Marks a method as a task with optional weight |
|
|
16
|
+
| **wait_time** | Think time between tasks |
|
|
17
|
+
| **HttpUser** | Preconfigured User with HTTP client |
|
|
18
|
+
| **FastHttpUser** | High-performance HTTP client (gevent-based) |
|
|
19
|
+
| **events** | Hooks for setup, teardown, request success/failure |
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Basic Script
|
|
24
|
+
|
|
25
|
+
```python
|
|
26
|
+
from locust import HttpUser, task, between
|
|
27
|
+
import json, random
|
|
28
|
+
|
|
29
|
+
class ShopUser(HttpUser):
|
|
30
|
+
wait_time = between(1, 4) # Think time: 1–4 seconds (uniform random)
|
|
31
|
+
host = "https://api.example.com"
|
|
32
|
+
|
|
33
|
+
def on_start(self):
|
|
34
|
+
"""Runs once per VU at startup"""
|
|
35
|
+
res = self.client.post("/auth/login", json={
|
|
36
|
+
"username": f"user{random.randint(1, 1000)}@test.com",
|
|
37
|
+
"password": "testpass123"
|
|
38
|
+
})
|
|
39
|
+
self.token = res.json()["access_token"]
|
|
40
|
+
self.client.headers.update({"Authorization": f"Bearer {self.token}"})
|
|
41
|
+
|
|
42
|
+
@task(3) # Weight: called 3x more than weight-1 tasks
|
|
43
|
+
def browse_products(self):
|
|
44
|
+
self.client.get("/products", name="GET /products")
|
|
45
|
+
|
|
46
|
+
@task(1)
|
|
47
|
+
def add_to_cart(self):
|
|
48
|
+
product_id = random.randint(1, 100)
|
|
49
|
+
with self.client.post(
|
|
50
|
+
f"/cart/items",
|
|
51
|
+
json={"productId": product_id, "qty": 1},
|
|
52
|
+
catch_response=True, # Manually handle response
|
|
53
|
+
name="POST /cart/items"
|
|
54
|
+
) as response:
|
|
55
|
+
if response.status_code == 200:
|
|
56
|
+
response.success()
|
|
57
|
+
else:
|
|
58
|
+
response.failure(f"Expected 200, got {response.status_code}")
|
|
59
|
+
|
|
60
|
+
def on_stop(self):
|
|
61
|
+
self.client.post("/auth/logout")
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Running Locust
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
# Web UI mode
|
|
70
|
+
locust -f locustfile.py --host https://api.example.com
|
|
71
|
+
|
|
72
|
+
# Headless (CLI) mode
|
|
73
|
+
locust -f locustfile.py \
|
|
74
|
+
--headless \
|
|
75
|
+
--users 100 \
|
|
76
|
+
--spawn-rate 10 \
|
|
77
|
+
--run-time 5m \
|
|
78
|
+
--host https://api.example.com \
|
|
79
|
+
--html report.html \
|
|
80
|
+
--csv results
|
|
81
|
+
|
|
82
|
+
# Distributed mode
|
|
83
|
+
# On master:
|
|
84
|
+
locust -f locustfile.py --master --users 1000 --spawn-rate 50
|
|
85
|
+
# On each worker:
|
|
86
|
+
locust -f locustfile.py --worker --master-host=<master-ip>
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Custom Wait Times
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
from locust import constant, constant_pacing, between, constant_throughput
|
|
95
|
+
|
|
96
|
+
wait_time = between(1, 5) # Uniform random 1–5s
|
|
97
|
+
wait_time = constant(2) # Fixed 2s
|
|
98
|
+
wait_time = constant_pacing(10) # Paces to 1 iteration per 10s (handles slow responses)
|
|
99
|
+
wait_time = constant_throughput(0.1) # Target 0.1 RPS per VU (10s average)
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Custom Events and Hooks
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
from locust import events
|
|
108
|
+
|
|
109
|
+
@events.test_start.add_listener
|
|
110
|
+
def on_test_start(environment, **kwargs):
|
|
111
|
+
print("Test starting — seeding test data")
|
|
112
|
+
|
|
113
|
+
@events.request.add_listener
|
|
114
|
+
def on_request(request_type, name, response_time, response_length, exception, **kwargs):
|
|
115
|
+
if exception:
|
|
116
|
+
print(f"FAILED: {name} — {exception}")
|
|
117
|
+
|
|
118
|
+
@events.test_stop.add_listener
|
|
119
|
+
def on_test_stop(environment, **kwargs):
|
|
120
|
+
print("Test finished — cleaning up data")
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## Locust-Specific Tips
|
|
126
|
+
|
|
127
|
+
- Always use `name=` parameter to group parameterized URLs (e.g., `/products/123` → `name="GET /products/{id}"`).
|
|
128
|
+
- Use `catch_response=True` for custom validation — HTTP 200 with error body passes silently otherwise.
|
|
129
|
+
- Use `FastHttpUser` instead of `HttpUser` for CPU-bound or high-throughput scenarios.
|
|
130
|
+
- Use distributed mode above 500–1000 VUs — a single worker process saturates one CPU core.
|
|
131
|
+
|
|
132
|
+
> For anti-patterns, assertions, think time, and parameterization principles, see **Key Principles** in `SKILL.md`.
|
|
133
|
+
> For CI/CD integration and distributed execution details, see `references/topics/test-execution.md`.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# NeoLoad Reference
|
|
2
|
+
|
|
3
|
+
> Targets: NeoLoad 2024.x+
|
|
4
|
+
|
|
5
|
+
NeoLoad is a commercial enterprise performance testing tool from Tricentis, designed for large-scale, protocol-rich testing including HTTP, SAP, Citrix, and Flex.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Core Concepts
|
|
10
|
+
|
|
11
|
+
| Concept | Description |
|
|
12
|
+
|---|---|
|
|
13
|
+
| **Virtual User Profile** | Defines a user type and its behavior |
|
|
14
|
+
| **Population** | Group of VU profiles with percentage mix |
|
|
15
|
+
| **Scenario** | Load injection profile (ramp, constant, peak) |
|
|
16
|
+
| **Container** | Transaction group (like JMeter Transaction Controller) |
|
|
17
|
+
| **Variable Extractor** | Correlation mechanism |
|
|
18
|
+
| **SLA Profile** | KPI thresholds; alerts and pass/fail criteria |
|
|
19
|
+
| **Controller** | Orchestrates test execution |
|
|
20
|
+
| **Load Generator** | Injects simulated users |
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Workload Design in NeoLoad
|
|
25
|
+
|
|
26
|
+
1. **Record** via NeoLoad browser proxy or VU recorder
|
|
27
|
+
2. **Parameterize** using Variable Extractors (Regexp, XPath, JSONPath) and File Variables
|
|
28
|
+
3. **Apply SLA Profile** with thresholds for response time, error rate, throughput
|
|
29
|
+
4. **Design Population** mixing multiple VU profiles
|
|
30
|
+
5. **Configure Scenario** with ramp-up policies and constant phase
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## CLI / API Execution
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
# Run from command line
|
|
38
|
+
NeoLoadCmd -project mytest.nlp \
|
|
39
|
+
-scenario "Regression_Load" \
|
|
40
|
+
-testResultName "CI_Run_${BUILD_NUMBER}" \
|
|
41
|
+
-leaseServer neoload-controller:7400
|
|
42
|
+
|
|
43
|
+
# REST API trigger (for CI/CD)
|
|
44
|
+
curl -X POST "https://neoload-api.tricentis.com/v3/tests/{testId}/start" \
|
|
45
|
+
-H "accountToken: $NEOLOAD_TOKEN" \
|
|
46
|
+
-d '{"scenario": "Load_Scenario"}'
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## NeoLoad-Specific Tips
|
|
52
|
+
|
|
53
|
+
- Always set **Network Emulation** to match target environment (LAN, WAN, mobile).
|
|
54
|
+
- Use **Shared Containers** for reusable sequences (e.g., authentication flow).
|
|
55
|
+
- Configure **Cache and Cookie Policies** per application behavior.
|
|
56
|
+
- Use **NeoLoad Web** for centralized result storage, trend analysis, and team collaboration.
|
|
57
|
+
- Integrate with **Dynatrace/AppDynamics** via built-in APM connectors.
|
|
58
|
+
- Use **as-code YAML definitions** (NeoLoad as Code) for version-controlled test configs.
|
|
59
|
+
|
|
60
|
+
> For anti-patterns, assertions, think time, and parameterization principles, see **Key Principles** in `SKILL.md`.
|
|
61
|
+
> For CI/CD integration details, see `references/topics/test-execution.md`.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# OctoPerf Reference
|
|
2
|
+
|
|
3
|
+
> Targets: OctoPerf SaaS (current)
|
|
4
|
+
|
|
5
|
+
OctoPerf is a cloud-based SaaS performance testing platform built on top of JMeter. It provides a professional UI for test design, cloud execution, and centralized result management.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Key Capabilities
|
|
10
|
+
|
|
11
|
+
| Feature | Description |
|
|
12
|
+
|---|---|
|
|
13
|
+
| **JMeter import/export** | Import existing `.jmx` files; export OctoPerf designs as JMeter |
|
|
14
|
+
| **Visual scenario builder** | GUI for scripting without raw JMeter XML editing |
|
|
15
|
+
| **Cloud execution** | On-demand cloud load generators (AWS regions) |
|
|
16
|
+
| **Real-time dashboards** | Live metrics during test run |
|
|
17
|
+
| **Trend analysis** | Compare runs over time |
|
|
18
|
+
| **SLA alerts** | Email/Slack notifications on KPI breach |
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Workflow
|
|
23
|
+
|
|
24
|
+
1. **Import or Record** - upload existing JMX or use OctoPerf's HAR import (record browser -> export HAR -> import).
|
|
25
|
+
2. **Parameterize** - use OctoPerf variable extractors (JSON, Regexp, Header) in the GUI.
|
|
26
|
+
3. **Configure Load Profile** - ramp-up wizard or custom curve editor.
|
|
27
|
+
4. **Select Regions** - pick cloud injection regions (US-East, EU-West, APAC, etc.).
|
|
28
|
+
5. **Run and Monitor** - real-time dashboard with RPS, response time percentiles, error rate.
|
|
29
|
+
6. **Analyze** - use built-in report builder or export to CSV/JSON.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## OctoPerf-Specific Tips
|
|
34
|
+
|
|
35
|
+
- Use OctoPerf's **HAR importer** to quickly create scripts from browser recordings.
|
|
36
|
+
- Leverage **Virtual User Groups** to model different user populations.
|
|
37
|
+
- Store test plans in **Workspaces** with version history.
|
|
38
|
+
- Use the **REST API** to trigger runs from CI/CD:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
# Trigger run via API
|
|
42
|
+
curl -X POST "https://api.octoperf.com/analysis/executions" \
|
|
43
|
+
-H "X-Api-Key: $OCTOPERF_API_KEY" \
|
|
44
|
+
-d '{"scenarioId": "abc123", "name": "CI Build #42"}'
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
- Always set **SLA thresholds** in the test profile so CI gates work reliably.
|
|
48
|
+
|
|
49
|
+
> For anti-patterns, assertions, think time, and parameterization principles, see **Key Principles** in `SKILL.md`.
|
|
50
|
+
> For CI/CD integration details, see `references/topics/test-execution.md`.
|