@assertrx/dino 1.0.10 → 1.0.12
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/package.json +1 -1
- package/prompts/generate-k6-test-from-endpoint.md +68 -0
- package/prompts/generate-k6-test-from-openapi.md +85 -0
- package/prompts/setup-k6.md +130 -0
- package/prompts/setup-promptfoo.md +103 -0
- package/scripts/api-server.mjs +28 -0
- package/skills/analyzing-test-results/SKILL.md +150 -0
- package/skills/analyzing-test-results/reference/bottleneck-patterns.md +130 -0
- package/skills/analyzing-test-results/reference/metrics.md +134 -0
- package/skills/analyzing-test-results/reference/visualization.md +152 -0
- package/skills/designing-test-scenarios/SKILL.md +247 -0
- package/skills/designing-test-scenarios/reference/executors.md +215 -0
- package/skills/designing-test-scenarios/reference/test-types.md +215 -0
- package/skills/designing-test-scenarios/reference/thresholds.md +208 -0
- package/skills/generating-api-load-tests/SKILL.md +199 -0
- package/skills/generating-api-load-tests/reference/data-parameterization.md +343 -0
- package/skills/generating-api-load-tests/reference/grpc.md +315 -0
- package/skills/generating-api-load-tests/reference/http.md +380 -0
- package/skills/generating-api-load-tests/reference/websocket.md +369 -0
- package/skills/generating-browser-tests/SKILL.md +269 -0
- package/skills/generating-browser-tests/reference/browser-api.md +251 -0
- package/skills/generating-browser-tests/reference/web-vitals.md +148 -0
- package/skills/generating-tests-from-code/SKILL.md +142 -0
- package/skills/generating-tests-from-code/reference/auth-analysis.md +220 -0
- package/skills/generating-tests-from-code/reference/framework-patterns.md +242 -0
- package/skills/generating-tests-from-openapi/SKILL.md +234 -0
- package/skills/generating-tests-from-openapi/reference/openapi-auth-mapping.md +247 -0
- package/skills/generating-tests-from-openapi/reference/openapi-parsing.md +194 -0
- package/skills/operating-k6-in-ci-cd/SKILL.md +98 -0
- package/skills/operating-k6-in-ci-cd/reference/ci-cd-pipelines.md +265 -0
- package/skills/operating-k6-in-ci-cd/reference/extensions.md +144 -0
- package/skills/operating-k6-in-ci-cd/reference/k6-operator.md +214 -0
- package/skills/promptfoo/SKILL.md +121 -0
- package/skills/promptfoo/reference/assert-types.md +74 -0
- package/skills/promptfoo/reference/providers.md +70 -0
- package/skills/testing-resilience/SKILL.md +230 -0
- package/skills/testing-resilience/reference/fault-injection.md +153 -0
- package/skills/testing-resilience/reference/resilience-patterns.md +500 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# k6 Bottleneck Patterns Reference
|
|
2
|
+
|
|
3
|
+
## Diagnostic Matrix
|
|
4
|
+
|
|
5
|
+
| Symptom | Primary Metric | Root Cause | Action |
|
|
6
|
+
|---------|---------------|------------|--------|
|
|
7
|
+
| High blocked time | `http_req_blocked` > 100ms | Connection pool exhaustion, DNS issues | Increase connection pool, use HTTP keep-alive |
|
|
8
|
+
| High connecting time | `http_req_connecting` > 50ms | Server distance, TCP overhead | Use closer servers, CDN, connection reuse |
|
|
9
|
+
| High TLS time | `http_req_tls_handshaking` > 100ms | New TLS connection per request | Enable keep-alive, TLS session resumption |
|
|
10
|
+
| High waiting time | `http_req_waiting` > 500ms | Slow server processing | Optimize backend, DB queries, caching |
|
|
11
|
+
| High receiving time | `http_req_receiving` > 100ms | Large response body | Compress responses, paginate, reduce payload |
|
|
12
|
+
| High error rate | `http_req_failed` > 1% | Server overload, bugs | Check error codes, server logs, capacity |
|
|
13
|
+
| Low throughput | `http_reqs` rate declining | Resource saturation | Scale infrastructure, optimize code |
|
|
14
|
+
| Dropped iterations | `dropped_iterations` > 0 | Not enough VUs for target rate | Increase `preAllocatedVUs` or `maxVUs` |
|
|
15
|
+
|
|
16
|
+
## Pattern 1: Connection Pool Exhaustion
|
|
17
|
+
|
|
18
|
+
**Symptoms:**
|
|
19
|
+
- `http_req_blocked` p95 > 100ms (often > 1s)
|
|
20
|
+
- `http_req_blocked` increases over time
|
|
21
|
+
- `http_req_connecting` stays low
|
|
22
|
+
|
|
23
|
+
**Diagnosis:** k6 cannot open new connections fast enough. Requests queue waiting for available connections.
|
|
24
|
+
|
|
25
|
+
**Solutions:**
|
|
26
|
+
- Check target server connection limits
|
|
27
|
+
- Reduce concurrent VU count
|
|
28
|
+
- Add think time (`sleep()`) between requests
|
|
29
|
+
- Check if server supports HTTP/2 (multiplexing)
|
|
30
|
+
|
|
31
|
+
## Pattern 2: TLS Overhead
|
|
32
|
+
|
|
33
|
+
**Symptoms:**
|
|
34
|
+
- `http_req_tls_handshaking` consistently > 50ms
|
|
35
|
+
- First requests have much higher duration than subsequent ones
|
|
36
|
+
- `http_req_blocked` correlates with TLS timing
|
|
37
|
+
|
|
38
|
+
**Diagnosis:** New TLS connections being established for each request instead of reusing.
|
|
39
|
+
|
|
40
|
+
**Solutions:**
|
|
41
|
+
- k6 reuses connections by default within an iteration
|
|
42
|
+
- Ensure server supports TLS session resumption
|
|
43
|
+
- Check if `noConnectionReuse` option is accidentally set
|
|
44
|
+
- Consider HTTP/2 for multiplexing over single connection
|
|
45
|
+
|
|
46
|
+
## Pattern 3: Server-Side Bottleneck
|
|
47
|
+
|
|
48
|
+
**Symptoms:**
|
|
49
|
+
- `http_req_waiting` (TTFB) increases as VUs increase
|
|
50
|
+
- `http_req_waiting` is the dominant component of duration
|
|
51
|
+
- `http_req_sending` and `http_req_receiving` remain low
|
|
52
|
+
|
|
53
|
+
**Diagnosis:** Server is struggling under load. Could be CPU, memory, database, or application bottleneck.
|
|
54
|
+
|
|
55
|
+
**Solutions:**
|
|
56
|
+
- Profile server-side code
|
|
57
|
+
- Optimize database queries (add indexes, caching)
|
|
58
|
+
- Scale horizontally (add servers)
|
|
59
|
+
- Implement caching (Redis, CDN)
|
|
60
|
+
- Check for thread/connection pool limits
|
|
61
|
+
|
|
62
|
+
## Pattern 4: Response Size Bottleneck
|
|
63
|
+
|
|
64
|
+
**Symptoms:**
|
|
65
|
+
- `http_req_receiving` is high relative to total duration
|
|
66
|
+
- `data_received` is very high
|
|
67
|
+
- Throughput drops as response sizes increase
|
|
68
|
+
|
|
69
|
+
**Diagnosis:** Large response payloads consuming bandwidth and processing time.
|
|
70
|
+
|
|
71
|
+
**Solutions:**
|
|
72
|
+
- Enable response compression (gzip, brotli)
|
|
73
|
+
- Implement pagination for list endpoints
|
|
74
|
+
- Return only necessary fields (field selection)
|
|
75
|
+
- Use `discardResponseBodies: true` in k6 options if body isn't needed
|
|
76
|
+
|
|
77
|
+
## Pattern 5: Gradual Degradation (Soak Test)
|
|
78
|
+
|
|
79
|
+
**Symptoms:**
|
|
80
|
+
- Metrics gradually worsen over time
|
|
81
|
+
- `http_req_duration` slowly increases during soak test
|
|
82
|
+
- Error rate slowly creeps up
|
|
83
|
+
|
|
84
|
+
**Diagnosis:** Memory leak, connection leak, or resource exhaustion in server.
|
|
85
|
+
|
|
86
|
+
**Solutions:**
|
|
87
|
+
- Monitor server-side memory usage
|
|
88
|
+
- Check for connection/handle leaks
|
|
89
|
+
- Verify database connection pool sizing
|
|
90
|
+
- Check log file growth
|
|
91
|
+
- Monitor disk space
|
|
92
|
+
|
|
93
|
+
## Pattern 6: Sudden Failure (Breakpoint)
|
|
94
|
+
|
|
95
|
+
**Symptoms:**
|
|
96
|
+
- Metrics suddenly spike at specific VU count or RPS
|
|
97
|
+
- Error rate jumps from ~0% to high percentage
|
|
98
|
+
- `http_req_duration` increases dramatically
|
|
99
|
+
|
|
100
|
+
**Diagnosis:** System has hit a hard limit (connection limit, thread pool, memory).
|
|
101
|
+
|
|
102
|
+
**Solutions:**
|
|
103
|
+
- Identify the exact threshold where failure begins
|
|
104
|
+
- Check server error logs at that timestamp
|
|
105
|
+
- Common limits: max connections, max threads, memory, file descriptors
|
|
106
|
+
- Tune the specific limit or scale infrastructure
|
|
107
|
+
|
|
108
|
+
## Correlation Between Metrics
|
|
109
|
+
|
|
110
|
+
**Healthy test:**
|
|
111
|
+
- `http_req_duration` stable across all percentiles
|
|
112
|
+
- `http_req_failed` near 0%
|
|
113
|
+
- `http_reqs` rate matches expected throughput
|
|
114
|
+
- `dropped_iterations` = 0
|
|
115
|
+
|
|
116
|
+
**Signs of trouble:**
|
|
117
|
+
- p99 >> p50 (high variance = inconsistent performance)
|
|
118
|
+
- `http_req_failed` increasing over time
|
|
119
|
+
- `http_reqs` rate declining while VUs are constant
|
|
120
|
+
- `http_req_blocked` growing (connection issues)
|
|
121
|
+
- `dropped_iterations` increasing (can't keep up with arrival rate)
|
|
122
|
+
|
|
123
|
+
## Performance Ratio Guidelines
|
|
124
|
+
|
|
125
|
+
| Ratio | Healthy | Warning | Critical |
|
|
126
|
+
|-------|---------|---------|----------|
|
|
127
|
+
| p95 / p50 | < 2x | 2-5x | > 5x |
|
|
128
|
+
| p99 / p50 | < 3x | 3-10x | > 10x |
|
|
129
|
+
| Error rate | < 0.1% | 0.1-1% | > 1% |
|
|
130
|
+
| TTFB / Duration | < 80% | 80-95% | > 95% |
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# k6 Metrics Reference
|
|
2
|
+
|
|
3
|
+
## Built-in HTTP Metrics
|
|
4
|
+
|
|
5
|
+
| Metric | Type | Description |
|
|
6
|
+
|--------|------|-------------|
|
|
7
|
+
| `http_reqs` | Counter | Total HTTP requests made |
|
|
8
|
+
| `http_req_duration` | Trend | Total request time (sending + waiting + receiving) |
|
|
9
|
+
| `http_req_blocked` | Trend | Time blocked before initiating request |
|
|
10
|
+
| `http_req_connecting` | Trend | Time establishing TCP connection |
|
|
11
|
+
| `http_req_tls_handshaking` | Trend | Time performing TLS handshake |
|
|
12
|
+
| `http_req_sending` | Trend | Time sending request body |
|
|
13
|
+
| `http_req_waiting` | Trend | Time waiting for server response (TTFB) |
|
|
14
|
+
| `http_req_receiving` | Trend | Time receiving response body |
|
|
15
|
+
| `http_req_failed` | Rate | Rate of failed requests (non-2xx/3xx or expected status) |
|
|
16
|
+
|
|
17
|
+
## Execution Metrics
|
|
18
|
+
|
|
19
|
+
| Metric | Type | Description |
|
|
20
|
+
|--------|------|-------------|
|
|
21
|
+
| `vus` | Gauge | Current number of active virtual users |
|
|
22
|
+
| `vus_max` | Gauge | Maximum possible number of VUs |
|
|
23
|
+
| `iterations` | Counter | Total number of completed iterations |
|
|
24
|
+
| `iteration_duration` | Trend | Time to complete one full iteration |
|
|
25
|
+
| `dropped_iterations` | Counter | Iterations that couldn't start (arrival-rate executors) |
|
|
26
|
+
| `data_received` | Counter | Amount of data received (bytes) |
|
|
27
|
+
| `data_sent` | Counter | Amount of data sent (bytes) |
|
|
28
|
+
|
|
29
|
+
## Browser Metrics
|
|
30
|
+
|
|
31
|
+
| Metric | Type | Description |
|
|
32
|
+
|--------|------|-------------|
|
|
33
|
+
| `browser_web_vital_lcp` | Trend | Largest Contentful Paint |
|
|
34
|
+
| `browser_web_vital_fcp` | Trend | First Contentful Paint |
|
|
35
|
+
| `browser_web_vital_cls` | Trend | Cumulative Layout Shift |
|
|
36
|
+
| `browser_web_vital_inp` | Trend | Interaction to Next Paint |
|
|
37
|
+
| `browser_web_vital_ttfb` | Trend | Time to First Byte |
|
|
38
|
+
| `browser_web_vital_fid` | Trend | First Input Delay (deprecated) |
|
|
39
|
+
| `browser_data_received` | Counter | Browser data received (bytes) |
|
|
40
|
+
| `browser_data_sent` | Counter | Browser data sent (bytes) |
|
|
41
|
+
| `browser_http_req_duration` | Trend | Browser HTTP request duration |
|
|
42
|
+
| `browser_http_req_failed` | Rate | Browser failed request rate |
|
|
43
|
+
|
|
44
|
+
## WebSocket Metrics
|
|
45
|
+
|
|
46
|
+
| Metric | Type | Description |
|
|
47
|
+
|--------|------|-------------|
|
|
48
|
+
| `ws_connecting` | Trend | WebSocket connection time |
|
|
49
|
+
| `ws_session_duration` | Trend | Total session duration |
|
|
50
|
+
| `ws_msgs_sent` | Counter | Messages sent |
|
|
51
|
+
| `ws_msgs_received` | Counter | Messages received |
|
|
52
|
+
| `ws_ping` | Trend | Ping round-trip time |
|
|
53
|
+
| `ws_sessions` | Counter | Sessions started |
|
|
54
|
+
|
|
55
|
+
## gRPC Metrics
|
|
56
|
+
|
|
57
|
+
| Metric | Type | Description |
|
|
58
|
+
|--------|------|-------------|
|
|
59
|
+
| `grpc_req_duration` | Trend | gRPC request duration |
|
|
60
|
+
| `grpc_streams` | Counter | Streams initiated |
|
|
61
|
+
| `grpc_streams_msgs_sent` | Counter | Stream messages sent |
|
|
62
|
+
| `grpc_streams_msgs_received` | Counter | Stream messages received |
|
|
63
|
+
|
|
64
|
+
## Check Metrics
|
|
65
|
+
|
|
66
|
+
| Metric | Type | Description |
|
|
67
|
+
|--------|------|-------------|
|
|
68
|
+
| `checks` | Rate | Overall rate of successful checks |
|
|
69
|
+
|
|
70
|
+
## Group Metrics
|
|
71
|
+
|
|
72
|
+
| Metric | Type | Description |
|
|
73
|
+
|--------|------|-------------|
|
|
74
|
+
| `group_duration` | Trend | Time to complete a group |
|
|
75
|
+
|
|
76
|
+
## Custom Metric Types
|
|
77
|
+
|
|
78
|
+
### Counter — Cumulative sum
|
|
79
|
+
|
|
80
|
+
```javascript
|
|
81
|
+
import { Counter } from 'k6/metrics';
|
|
82
|
+
const errors = new Counter('api_errors');
|
|
83
|
+
|
|
84
|
+
errors.add(1); // Increment by 1
|
|
85
|
+
errors.add(5); // Increment by 5
|
|
86
|
+
// Threshold: count, rate
|
|
87
|
+
// 'api_errors': ['count<100']
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Gauge — Instantaneous value
|
|
91
|
+
|
|
92
|
+
```javascript
|
|
93
|
+
import { Gauge } from 'k6/metrics';
|
|
94
|
+
const queueSize = new Gauge('queue_size');
|
|
95
|
+
|
|
96
|
+
queueSize.add(42); // Set value
|
|
97
|
+
// Threshold: value
|
|
98
|
+
// 'queue_size': ['value<1000']
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Rate — Percentage of non-zero values
|
|
102
|
+
|
|
103
|
+
```javascript
|
|
104
|
+
import { Rate } from 'k6/metrics';
|
|
105
|
+
const successRate = new Rate('success_rate');
|
|
106
|
+
|
|
107
|
+
successRate.add(true); // Success (1)
|
|
108
|
+
successRate.add(false); // Failure (0)
|
|
109
|
+
successRate.add(1); // Success
|
|
110
|
+
successRate.add(0); // Failure
|
|
111
|
+
// Threshold: rate
|
|
112
|
+
// 'success_rate': ['rate>0.95']
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Trend — Statistics over time
|
|
116
|
+
|
|
117
|
+
```javascript
|
|
118
|
+
import { Trend } from 'k6/metrics';
|
|
119
|
+
const apiLatency = new Trend('api_latency');
|
|
120
|
+
|
|
121
|
+
apiLatency.add(150); // Add sample (ms)
|
|
122
|
+
apiLatency.add(200);
|
|
123
|
+
// Threshold: avg, min, max, med, p(N)
|
|
124
|
+
// 'api_latency': ['p(95)<500', 'avg<200']
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Metric Type Aggregation Methods
|
|
128
|
+
|
|
129
|
+
| Type | Available Methods | Example |
|
|
130
|
+
|------|------------------|---------|
|
|
131
|
+
| Counter | `count`, `rate` | `count<100`, `rate>10` |
|
|
132
|
+
| Gauge | `value` | `value<1000` |
|
|
133
|
+
| Rate | `rate` | `rate>0.95` |
|
|
134
|
+
| Trend | `avg`, `min`, `max`, `med`, `p(N)` | `p(95)<500`, `avg<200` |
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# k6 Results Visualization Reference
|
|
2
|
+
|
|
3
|
+
## Output Options
|
|
4
|
+
|
|
5
|
+
### Console Summary (Default)
|
|
6
|
+
|
|
7
|
+
k6 prints an end-of-test summary to stdout by default. No configuration needed.
|
|
8
|
+
|
|
9
|
+
### JSON Lines (Real-Time Streaming)
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
k6 run --out json=results.json script.js
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Each line is a JSON object with metric data, timestamps, and tags. Useful for post-processing.
|
|
16
|
+
|
|
17
|
+
### CSV Output
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
k6 run --out csv=results.csv script.js
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Web Dashboard (Built-in)
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
K6_WEB_DASHBOARD=true k6 run script.js
|
|
27
|
+
# Access at http://localhost:5665
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Real-time visualization in the browser. Shows charts for all metrics.
|
|
31
|
+
|
|
32
|
+
### Multiple Outputs
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
k6 run --out json=results.json --out csv=results.csv script.js
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## handleSummary() Customization
|
|
39
|
+
|
|
40
|
+
Override the default end-of-test summary:
|
|
41
|
+
|
|
42
|
+
```javascript
|
|
43
|
+
import { textSummary } from 'https://jslib.k6.io/k6-summary/0.1.0/index.js';
|
|
44
|
+
|
|
45
|
+
export function handleSummary(data) {
|
|
46
|
+
return {
|
|
47
|
+
// Console output
|
|
48
|
+
stdout: textSummary(data, { indent: ' ', enableColors: true }),
|
|
49
|
+
// JSON file
|
|
50
|
+
'summary.json': JSON.stringify(data, null, 2),
|
|
51
|
+
// Custom HTML report
|
|
52
|
+
'report.html': generateHtmlReport(data),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function generateHtmlReport(data) {
|
|
57
|
+
const metrics = data.metrics;
|
|
58
|
+
return `
|
|
59
|
+
<html>
|
|
60
|
+
<body>
|
|
61
|
+
<h1>k6 Test Report</h1>
|
|
62
|
+
<h2>HTTP Request Duration</h2>
|
|
63
|
+
<p>Average: ${metrics.http_req_duration.values.avg.toFixed(2)}ms</p>
|
|
64
|
+
<p>P95: ${metrics.http_req_duration.values['p(95)'].toFixed(2)}ms</p>
|
|
65
|
+
<p>P99: ${metrics.http_req_duration.values['p(99)'].toFixed(2)}ms</p>
|
|
66
|
+
<h2>Error Rate</h2>
|
|
67
|
+
<p>${(metrics.http_req_failed.values.rate * 100).toFixed(2)}%</p>
|
|
68
|
+
<h2>Throughput</h2>
|
|
69
|
+
<p>${metrics.http_reqs.values.rate.toFixed(2)} req/s</p>
|
|
70
|
+
</body>
|
|
71
|
+
</html>
|
|
72
|
+
`;
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### handleSummary Data Structure
|
|
77
|
+
|
|
78
|
+
```javascript
|
|
79
|
+
{
|
|
80
|
+
root_group: {
|
|
81
|
+
name: '',
|
|
82
|
+
path: '',
|
|
83
|
+
groups: [...],
|
|
84
|
+
checks: [...],
|
|
85
|
+
},
|
|
86
|
+
metrics: {
|
|
87
|
+
http_req_duration: {
|
|
88
|
+
type: 'trend',
|
|
89
|
+
contains: 'time',
|
|
90
|
+
values: {
|
|
91
|
+
avg: 131.01,
|
|
92
|
+
min: 116.4,
|
|
93
|
+
med: 127.6,
|
|
94
|
+
max: 196.38,
|
|
95
|
+
'p(90)': 146.21,
|
|
96
|
+
'p(95)': 176.91,
|
|
97
|
+
},
|
|
98
|
+
thresholds: {
|
|
99
|
+
'p(95)<500': { ok: true },
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
// ... other metrics
|
|
103
|
+
},
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Grafana Cloud k6
|
|
108
|
+
|
|
109
|
+
### Running with Cloud Results
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
# Set token
|
|
113
|
+
export K6_CLOUD_TOKEN=your-token-here
|
|
114
|
+
|
|
115
|
+
# Run locally, send results to cloud
|
|
116
|
+
k6 cloud run --local-execution script.js
|
|
117
|
+
|
|
118
|
+
# Run entirely in cloud
|
|
119
|
+
k6 cloud run script.js
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Cloud Dashboard Features
|
|
123
|
+
|
|
124
|
+
- Real-time metric visualization
|
|
125
|
+
- Performance trend comparison across runs
|
|
126
|
+
- Threshold pass/fail tracking
|
|
127
|
+
- Team sharing and collaboration
|
|
128
|
+
- Historical result storage
|
|
129
|
+
|
|
130
|
+
## Post-Processing JSON Results
|
|
131
|
+
|
|
132
|
+
### Using jq
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
# Extract all http_req_duration data points
|
|
136
|
+
cat results.json | jq 'select(.type=="Point" and .metric=="http_req_duration")'
|
|
137
|
+
|
|
138
|
+
# Get all failed requests
|
|
139
|
+
cat results.json | jq 'select(.type=="Point" and .metric=="http_req_failed" and .data.value==1)'
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Using Python
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
import json
|
|
146
|
+
|
|
147
|
+
with open('results.json') as f:
|
|
148
|
+
for line in f:
|
|
149
|
+
data = json.loads(line)
|
|
150
|
+
if data.get('metric') == 'http_req_duration':
|
|
151
|
+
print(f"Duration: {data['data']['value']}ms")
|
|
152
|
+
```
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: designing-test-scenarios
|
|
3
|
+
description: Use when designing k6 load profiles, choosing executors, configuring VU patterns, setting thresholds, or planning test scenarios. Use when the user asks about stress test, spike test, soak test, breakpoint test, load model, executor selection, or pass/fail criteria.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Designing k6 Test Scenarios
|
|
7
|
+
|
|
8
|
+
Design load profiles, select executors, configure thresholds, and orchestrate multi-scenario tests. This skill helps choose the right approach for your performance testing goals.
|
|
9
|
+
|
|
10
|
+
## Test Type Selection Guide
|
|
11
|
+
|
|
12
|
+
Choose a test type based on your goal:
|
|
13
|
+
|
|
14
|
+
| Goal | Test Type | VUs | Duration | Details |
|
|
15
|
+
|------|-----------|-----|----------|---------|
|
|
16
|
+
| Verify script works, get baseline | **Smoke** | 2-5 | 30s-3m | Run after every script change |
|
|
17
|
+
| Assess typical load performance | **Load** | Average production | 5-60min | Gradual ramp-up, sustained plateau |
|
|
18
|
+
| Check behavior under heavy load | **Stress** | 50-100%+ above avg | 10-60min | Higher than normal, expect degradation |
|
|
19
|
+
| Detect long-running issues (leaks) | **Soak** | Average production | 3-72 hours | Same as load but extended duration |
|
|
20
|
+
| Survive sudden traffic burst | **Spike** | Very high, sudden | 2-5min | Rapid ramp, minimal plateau |
|
|
21
|
+
| Find system capacity limits | **Breakpoint** | Incremental to failure | Until break | Continuous ramp, no plateau |
|
|
22
|
+
|
|
23
|
+
See [reference/test-types.md](reference/test-types.md) for detailed configurations and stage patterns per test type.
|
|
24
|
+
|
|
25
|
+
## Executor Selection
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
What drives your test?
|
|
29
|
+
│
|
|
30
|
+
├─ Fixed number of total iterations → shared-iterations
|
|
31
|
+
│ (e.g., "run exactly 1000 requests")
|
|
32
|
+
│
|
|
33
|
+
├─ Fixed iterations per VU → per-vu-iterations
|
|
34
|
+
│ (e.g., "each VU runs exactly 50 requests")
|
|
35
|
+
│
|
|
36
|
+
├─ Constant VU count for duration → constant-vus
|
|
37
|
+
│ (e.g., "keep 20 users active for 5 minutes")
|
|
38
|
+
│
|
|
39
|
+
├─ Variable VU count over time → ramping-vus
|
|
40
|
+
│ (e.g., "ramp from 0 to 100 users over 10 minutes")
|
|
41
|
+
│
|
|
42
|
+
├─ Constant request rate (RPS) → constant-arrival-rate
|
|
43
|
+
│ (e.g., "maintain 50 requests/second")
|
|
44
|
+
│
|
|
45
|
+
└─ Variable request rate over time → ramping-arrival-rate
|
|
46
|
+
(e.g., "ramp from 10 to 100 requests/second")
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
See [reference/executors.md](reference/executors.md) for complete configuration parameters and examples for each executor.
|
|
50
|
+
|
|
51
|
+
## Open vs Closed Model
|
|
52
|
+
|
|
53
|
+
**Closed Model** (VU-based executors): Next iteration starts when previous finishes. System slowdown reduces throughput.
|
|
54
|
+
- Executors: `shared-iterations`, `per-vu-iterations`, `constant-vus`, `ramping-vus`
|
|
55
|
+
- Use for: Simple tests, when iteration count matters more than rate
|
|
56
|
+
|
|
57
|
+
**Open Model** (arrival-rate executors): Iterations start at fixed rate regardless of response time. Maintains throughput even under stress.
|
|
58
|
+
- Executors: `constant-arrival-rate`, `ramping-arrival-rate`
|
|
59
|
+
- Use for: Realistic RPS testing, stress testing, avoiding coordinated omission
|
|
60
|
+
|
|
61
|
+
**Recommendation:** Prefer open model (arrival-rate) for production-like load testing. It maintains target throughput even when the system slows down, giving more accurate results.
|
|
62
|
+
|
|
63
|
+
## Scenario Configuration
|
|
64
|
+
|
|
65
|
+
### Basic Scenario
|
|
66
|
+
|
|
67
|
+
```javascript
|
|
68
|
+
export const options = {
|
|
69
|
+
scenarios: {
|
|
70
|
+
my_scenario: {
|
|
71
|
+
executor: 'constant-vus',
|
|
72
|
+
vus: 50,
|
|
73
|
+
duration: '5m',
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Common Scenario Options
|
|
80
|
+
|
|
81
|
+
| Option | Type | Default | Description |
|
|
82
|
+
|--------|------|---------|-------------|
|
|
83
|
+
| `executor` | string | required | Executor type |
|
|
84
|
+
| `startTime` | string | `"0s"` | Delay before scenario starts |
|
|
85
|
+
| `gracefulStop` | string | `"30s"` | Wait time for in-flight iterations |
|
|
86
|
+
| `exec` | string | `"default"` | Exported function to execute |
|
|
87
|
+
| `env` | object | `{}` | Scenario-specific environment variables |
|
|
88
|
+
| `tags` | object | `{}` | Scenario-specific tags |
|
|
89
|
+
|
|
90
|
+
### Multi-Scenario Orchestration
|
|
91
|
+
|
|
92
|
+
Run different load patterns simultaneously or sequentially:
|
|
93
|
+
|
|
94
|
+
```javascript
|
|
95
|
+
export const options = {
|
|
96
|
+
scenarios: {
|
|
97
|
+
// Scenario 1: Browse products (majority of traffic)
|
|
98
|
+
browse: {
|
|
99
|
+
executor: 'constant-arrival-rate',
|
|
100
|
+
rate: 100,
|
|
101
|
+
timeUnit: '1s',
|
|
102
|
+
duration: '10m',
|
|
103
|
+
preAllocatedVUs: 50,
|
|
104
|
+
exec: 'browseProducts',
|
|
105
|
+
tags: { scenario: 'browse' },
|
|
106
|
+
},
|
|
107
|
+
// Scenario 2: Purchase flow (smaller portion)
|
|
108
|
+
purchase: {
|
|
109
|
+
executor: 'constant-arrival-rate',
|
|
110
|
+
rate: 10,
|
|
111
|
+
timeUnit: '1s',
|
|
112
|
+
duration: '10m',
|
|
113
|
+
preAllocatedVUs: 20,
|
|
114
|
+
startTime: '2m', // Start 2 minutes after browse
|
|
115
|
+
exec: 'purchaseItem',
|
|
116
|
+
tags: { scenario: 'purchase' },
|
|
117
|
+
},
|
|
118
|
+
// Scenario 3: Spike test (starts at 5 minutes)
|
|
119
|
+
spike: {
|
|
120
|
+
executor: 'ramping-vus',
|
|
121
|
+
startVUs: 0,
|
|
122
|
+
stages: [
|
|
123
|
+
{ duration: '30s', target: 500 },
|
|
124
|
+
{ duration: '1m', target: 500 },
|
|
125
|
+
{ duration: '30s', target: 0 },
|
|
126
|
+
],
|
|
127
|
+
startTime: '5m',
|
|
128
|
+
exec: 'browseProducts',
|
|
129
|
+
tags: { scenario: 'spike' },
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
export function browseProducts() { /* ... */ }
|
|
135
|
+
export function purchaseItem() { /* ... */ }
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Threshold Design
|
|
139
|
+
|
|
140
|
+
See [reference/thresholds.md](reference/thresholds.md) for complete threshold patterns.
|
|
141
|
+
|
|
142
|
+
### Quick Reference
|
|
143
|
+
|
|
144
|
+
```javascript
|
|
145
|
+
export const options = {
|
|
146
|
+
thresholds: {
|
|
147
|
+
// Response time
|
|
148
|
+
http_req_duration: ['p(95)<500', 'p(99)<1000'],
|
|
149
|
+
// Error rate
|
|
150
|
+
http_req_failed: ['rate<0.01'],
|
|
151
|
+
// Throughput
|
|
152
|
+
http_reqs: ['rate>100'],
|
|
153
|
+
// Check pass rate
|
|
154
|
+
checks: ['rate>0.99'],
|
|
155
|
+
// Custom metric
|
|
156
|
+
my_custom_trend: ['avg<200', 'p(90)<400'],
|
|
157
|
+
// Tag-based (different thresholds per endpoint)
|
|
158
|
+
'http_req_duration{name:GetUser}': ['p(95)<300'],
|
|
159
|
+
'http_req_duration{name:CreateOrder}': ['p(95)<800'],
|
|
160
|
+
},
|
|
161
|
+
};
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Abort on Failure
|
|
165
|
+
|
|
166
|
+
```javascript
|
|
167
|
+
export const options = {
|
|
168
|
+
thresholds: {
|
|
169
|
+
http_req_duration: [{
|
|
170
|
+
threshold: 'p(99)<1000',
|
|
171
|
+
abortOnFail: true,
|
|
172
|
+
delayAbortEval: '30s', // Wait 30s before evaluating
|
|
173
|
+
}],
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Custom Metrics
|
|
179
|
+
|
|
180
|
+
```javascript
|
|
181
|
+
import { Trend, Counter, Rate, Gauge } from 'k6/metrics';
|
|
182
|
+
|
|
183
|
+
const loginDuration = new Trend('login_duration');
|
|
184
|
+
const failedLogins = new Counter('failed_logins');
|
|
185
|
+
const successRate = new Rate('login_success_rate');
|
|
186
|
+
const activeUsers = new Gauge('active_users');
|
|
187
|
+
|
|
188
|
+
export const options = {
|
|
189
|
+
thresholds: {
|
|
190
|
+
login_duration: ['p(95)<2000'],
|
|
191
|
+
login_success_rate: ['rate>0.95'],
|
|
192
|
+
},
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
export default function () {
|
|
196
|
+
const start = Date.now();
|
|
197
|
+
const res = http.post(/* login request */);
|
|
198
|
+
loginDuration.add(Date.now() - start);
|
|
199
|
+
successRate.add(res.status === 200);
|
|
200
|
+
if (res.status !== 200) failedLogins.add(1);
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Tags and Groups
|
|
205
|
+
|
|
206
|
+
### Tags for Metric Filtering
|
|
207
|
+
|
|
208
|
+
```javascript
|
|
209
|
+
// Per-request tags
|
|
210
|
+
http.get(url, { tags: { name: 'Homepage', type: 'page' } });
|
|
211
|
+
|
|
212
|
+
// Per-scenario tags (in options)
|
|
213
|
+
scenarios: {
|
|
214
|
+
api_test: {
|
|
215
|
+
executor: 'constant-vus',
|
|
216
|
+
tags: { team: 'backend' },
|
|
217
|
+
},
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### Groups for Code Organization
|
|
222
|
+
|
|
223
|
+
```javascript
|
|
224
|
+
import { group } from 'k6';
|
|
225
|
+
|
|
226
|
+
export default function () {
|
|
227
|
+
group('Authentication', () => {
|
|
228
|
+
http.post('/login', credentials);
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
group('Browse Products', () => {
|
|
232
|
+
http.get('/products');
|
|
233
|
+
http.get('/products/1');
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
group('Checkout', () => {
|
|
237
|
+
http.post('/cart', item);
|
|
238
|
+
http.post('/checkout', payment);
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
## Related Skills
|
|
244
|
+
|
|
245
|
+
- For generating test scripts: `/k6:generating-api-load-tests`
|
|
246
|
+
- For interpreting test results: `/k6:analyzing-test-results`
|
|
247
|
+
- For browser-based testing scenarios: `/k6:generating-browser-tests`
|