@assertrx/dino 1.0.9 → 1.0.11

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.
Files changed (35) hide show
  1. package/package.json +1 -1
  2. package/prompts/generate-bdd-from-url.md +5 -1
  3. package/prompts/generate-k6-test-from-endpoint.md +68 -0
  4. package/prompts/generate-k6-test-from-openapi.md +85 -0
  5. package/prompts/setup-k6.md +130 -0
  6. package/scripts/api-server.mjs +32 -2
  7. package/skills/analyzing-test-results/SKILL.md +150 -0
  8. package/skills/analyzing-test-results/reference/bottleneck-patterns.md +130 -0
  9. package/skills/analyzing-test-results/reference/metrics.md +134 -0
  10. package/skills/analyzing-test-results/reference/visualization.md +152 -0
  11. package/skills/designing-test-scenarios/SKILL.md +247 -0
  12. package/skills/designing-test-scenarios/reference/executors.md +215 -0
  13. package/skills/designing-test-scenarios/reference/test-types.md +215 -0
  14. package/skills/designing-test-scenarios/reference/thresholds.md +208 -0
  15. package/skills/generating-api-load-tests/SKILL.md +199 -0
  16. package/skills/generating-api-load-tests/reference/data-parameterization.md +343 -0
  17. package/skills/generating-api-load-tests/reference/grpc.md +315 -0
  18. package/skills/generating-api-load-tests/reference/http.md +380 -0
  19. package/skills/generating-api-load-tests/reference/websocket.md +369 -0
  20. package/skills/generating-browser-tests/SKILL.md +269 -0
  21. package/skills/generating-browser-tests/reference/browser-api.md +251 -0
  22. package/skills/generating-browser-tests/reference/web-vitals.md +148 -0
  23. package/skills/generating-tests-from-code/SKILL.md +142 -0
  24. package/skills/generating-tests-from-code/reference/auth-analysis.md +220 -0
  25. package/skills/generating-tests-from-code/reference/framework-patterns.md +242 -0
  26. package/skills/generating-tests-from-openapi/SKILL.md +234 -0
  27. package/skills/generating-tests-from-openapi/reference/openapi-auth-mapping.md +247 -0
  28. package/skills/generating-tests-from-openapi/reference/openapi-parsing.md +194 -0
  29. package/skills/operating-k6-in-ci-cd/SKILL.md +98 -0
  30. package/skills/operating-k6-in-ci-cd/reference/ci-cd-pipelines.md +265 -0
  31. package/skills/operating-k6-in-ci-cd/reference/extensions.md +144 -0
  32. package/skills/operating-k6-in-ci-cd/reference/k6-operator.md +214 -0
  33. package/skills/testing-resilience/SKILL.md +230 -0
  34. package/skills/testing-resilience/reference/fault-injection.md +153 -0
  35. package/skills/testing-resilience/reference/resilience-patterns.md +500 -0
@@ -0,0 +1,230 @@
1
+ ---
2
+ name: testing-resilience
3
+ description: Use when creating chaos engineering or resilience tests with k6 and xk6-disruptor. Use when the user wants to inject faults (pod failures, network delays, HTTP errors) into Kubernetes services during load tests, validate circuit breakers, or test system recovery behavior.
4
+ ---
5
+
6
+ # Testing Resilience with k6
7
+
8
+ Create chaos and resilience tests using xk6-disruptor to inject faults into Kubernetes services during k6 load tests. Validates system behavior under failure conditions.
9
+
10
+ ## Overview
11
+
12
+ xk6-disruptor injects faults into Kubernetes pods and services while k6 generates load, allowing you to verify:
13
+ - System survives pod failures
14
+ - Graceful degradation under network issues
15
+ - Circuit breaker behavior
16
+ - Recovery time after fault removal
17
+ - Auto-scaling response to failures
18
+
19
+ ## Quick Start
20
+
21
+ ```javascript
22
+ import http from 'k6/http';
23
+ import { check, sleep } from 'k6';
24
+ import { ServiceDisruptor } from 'k6/x/disruptor';
25
+
26
+ export const options = {
27
+ scenarios: {
28
+ load: {
29
+ executor: 'constant-arrival-rate',
30
+ rate: 100,
31
+ timeUnit: '1s',
32
+ duration: '2m',
33
+ preAllocatedVUs: 50,
34
+ },
35
+ },
36
+ thresholds: {
37
+ http_req_failed: ['rate<0.3'], // Allow up to 30% errors during chaos
38
+ http_req_duration: ['p(95)<3000'], // Relaxed threshold during chaos
39
+ },
40
+ };
41
+
42
+ export function setup() {
43
+ // Inject fault: Add 500ms delay to 50% of requests
44
+ const disruptor = new ServiceDisruptor('my-service', 'default');
45
+ const fault = {
46
+ averageDelay: '500ms',
47
+ errorRate: 0.1, // 10% of requests return errors
48
+ errorCode: 503,
49
+ };
50
+ disruptor.injectHTTPFaults(fault, '60s');
51
+ }
52
+
53
+ export default function () {
54
+ const res = http.get('http://my-service.default.svc.cluster.local:8080/api');
55
+ check(res, {
56
+ 'not server error': (r) => r.status < 500 || r.status === 503,
57
+ });
58
+ sleep(0.1); // Intentional: adds backpressure per VU to avoid overwhelming the disrupted service
59
+ }
60
+ ```
61
+
62
+ ## Prerequisites
63
+
64
+ - **Kubernetes cluster** with target services deployed
65
+ - **k6 with xk6-disruptor** extension (or use automatic resolution)
66
+ - **RBAC permissions** for the k6 pod to manage target pods
67
+
68
+ ## Disruptor Types
69
+
70
+ ### ServiceDisruptor
71
+
72
+ Targets all pods behind a Kubernetes Service:
73
+
74
+ ```javascript
75
+ import { ServiceDisruptor } from 'k6/x/disruptor';
76
+
77
+ const disruptor = new ServiceDisruptor('service-name', 'namespace');
78
+ ```
79
+
80
+ ### PodDisruptor
81
+
82
+ Targets specific pods by label selector:
83
+
84
+ ```javascript
85
+ import { PodDisruptor } from 'k6/x/disruptor';
86
+
87
+ const disruptor = new PodDisruptor({
88
+ namespace: 'default',
89
+ select: { labels: { app: 'my-app' } },
90
+ });
91
+ ```
92
+
93
+ ## Fault Types
94
+
95
+ ### HTTP Faults
96
+
97
+ Inject delays and errors into HTTP responses:
98
+
99
+ ```javascript
100
+ disruptor.injectHTTPFaults(
101
+ {
102
+ averageDelay: '500ms', // Add delay to responses
103
+ delayVariation: '100ms', // Delay jitter
104
+ errorRate: 0.1, // 10% error rate
105
+ errorCode: 503, // Error HTTP status code
106
+ port: 8080, // Target port
107
+ exclude: '/health', // Exclude health check endpoint
108
+ },
109
+ '60s' // Fault duration
110
+ );
111
+ ```
112
+
113
+ ### gRPC Faults
114
+
115
+ Inject faults into gRPC services:
116
+
117
+ ```javascript
118
+ disruptor.injectGrpcFaults(
119
+ {
120
+ averageDelay: '500ms',
121
+ errorRate: 0.2,
122
+ statusCode: 14, // UNAVAILABLE
123
+ statusMessage: 'service overloaded',
124
+ },
125
+ '60s'
126
+ );
127
+ ```
128
+
129
+ ### Pod Termination
130
+
131
+ Kill pods to test recovery:
132
+
133
+ ```javascript
134
+ disruptor.terminatePods({
135
+ count: 1, // Number of pods to terminate
136
+ interval: '30s', // Wait between terminations
137
+ });
138
+ ```
139
+
140
+ See [reference/fault-injection.md](reference/fault-injection.md) for detailed fault configuration.
141
+
142
+ ## Resilience Test Patterns
143
+
144
+ ### Pattern 1: Graceful Degradation
145
+
146
+ Verify system degrades gracefully under partial failure:
147
+
148
+ ```javascript
149
+ export function setup() {
150
+ const disruptor = new ServiceDisruptor('backend-service', 'default');
151
+ disruptor.injectHTTPFaults({
152
+ averageDelay: '1000ms',
153
+ errorRate: 0.2,
154
+ errorCode: 503,
155
+ }, '90s');
156
+ }
157
+ ```
158
+
159
+ **Success criteria:** System returns degraded responses instead of cascading failures.
160
+
161
+ ### Pattern 2: Circuit Breaker Validation
162
+
163
+ Verify circuit breaker activates under error conditions:
164
+
165
+ ```javascript
166
+ export function setup() {
167
+ const disruptor = new ServiceDisruptor('downstream-service', 'default');
168
+ disruptor.injectHTTPFaults({
169
+ errorRate: 0.8, // 80% errors to trigger circuit breaker
170
+ errorCode: 500,
171
+ }, '60s');
172
+ }
173
+ ```
174
+
175
+ **Success criteria:** Upstream service returns fallback responses quickly (circuit open).
176
+
177
+ ### Pattern 3: Recovery Test
178
+
179
+ Verify system recovers after fault is removed:
180
+
181
+ ```javascript
182
+ export const options = {
183
+ scenarios: {
184
+ load: {
185
+ executor: 'constant-arrival-rate',
186
+ rate: 50,
187
+ timeUnit: '1s',
188
+ duration: '5m', // Total test: 5 minutes
189
+ preAllocatedVUs: 30,
190
+ },
191
+ },
192
+ };
193
+
194
+ export function setup() {
195
+ const disruptor = new ServiceDisruptor('my-service', 'default');
196
+ // Inject fault for only 2 minutes (test runs 5 minutes)
197
+ disruptor.injectHTTPFaults({
198
+ averageDelay: '2000ms',
199
+ errorRate: 0.5,
200
+ errorCode: 503,
201
+ }, '120s'); // Fault active for 2m, then 3m of recovery
202
+ }
203
+ ```
204
+
205
+ **Success criteria:** Metrics return to baseline within acceptable time after fault removal.
206
+
207
+ See [reference/resilience-patterns.md](reference/resilience-patterns.md) for more patterns.
208
+
209
+ ## Thresholds for Resilience Tests
210
+
211
+ Resilience tests need relaxed thresholds compared to normal load tests. Use tag-based thresholds to set different criteria for chaos and recovery phases:
212
+
213
+ ```javascript
214
+ export const options = {
215
+ thresholds: {
216
+ // During chaos: accept higher error rates
217
+ http_req_failed: ['rate<0.5'], // Up to 50% errors acceptable
218
+ // Overall response time upper bound (includes chaos phase)
219
+ http_req_duration: ['p(95)<5000'], // 5s max even during chaos
220
+ // Strict threshold for recovery phase only (tagged requests)
221
+ 'http_req_duration{phase:recovery}': ['p(95)<500'], // After recovery, back to normal
222
+ },
223
+ };
224
+ ```
225
+
226
+ ## Related Skills
227
+
228
+ - For generating load test scripts: `/k6:generating-api-load-tests`
229
+ - For CI/CD and Kubernetes setup: `/k6:operating-k6-in-ci-cd`
230
+ - For scenario design: `/k6:designing-test-scenarios`
@@ -0,0 +1,153 @@
1
+ # Fault Injection Reference
2
+
3
+ ## ServiceDisruptor
4
+
5
+ Targets all pods behind a Kubernetes Service.
6
+
7
+ ```javascript
8
+ import { ServiceDisruptor } from 'k6/x/disruptor';
9
+
10
+ const disruptor = new ServiceDisruptor('service-name', 'namespace');
11
+ ```
12
+
13
+ ### injectHTTPFaults(fault, duration)
14
+
15
+ | Parameter | Type | Description |
16
+ |-----------|------|-------------|
17
+ | `averageDelay` | string | Average delay added to responses (e.g., `'500ms'`) |
18
+ | `delayVariation` | string | Variation around averageDelay (e.g., `'100ms'`) |
19
+ | `errorRate` | float | Fraction of requests returning errors (0.0-1.0) |
20
+ | `errorCode` | integer | HTTP status code for injected errors |
21
+ | `errorBody` | string | Response body for injected errors |
22
+ | `port` | integer | Target port (required if service has multiple ports) |
23
+ | `exclude` | string | URL path prefix to exclude from faults |
24
+
25
+ ```javascript
26
+ disruptor.injectHTTPFaults({
27
+ averageDelay: '500ms',
28
+ delayVariation: '100ms',
29
+ errorRate: 0.1,
30
+ errorCode: 503,
31
+ errorBody: '{"error": "service unavailable"}',
32
+ port: 8080,
33
+ exclude: '/health',
34
+ }, '60s');
35
+ ```
36
+
37
+ ### injectGrpcFaults(fault, duration)
38
+
39
+ | Parameter | Type | Description |
40
+ |-----------|------|-------------|
41
+ | `averageDelay` | string | Average delay added to responses |
42
+ | `delayVariation` | string | Variation around averageDelay |
43
+ | `errorRate` | float | Fraction of requests returning errors (0.0-1.0) |
44
+ | `statusCode` | integer | gRPC status code for errors |
45
+ | `statusMessage` | string | gRPC status message for errors |
46
+ | `port` | integer | Target port |
47
+ | `exclude` | string | Service method to exclude |
48
+
49
+ ```javascript
50
+ disruptor.injectGrpcFaults({
51
+ averageDelay: '500ms',
52
+ errorRate: 0.2,
53
+ statusCode: 14, // UNAVAILABLE
54
+ statusMessage: 'injected fault',
55
+ }, '60s');
56
+ ```
57
+
58
+ ### terminatePods(options)
59
+
60
+ | Parameter | Type | Description |
61
+ |-----------|------|-------------|
62
+ | `count` | integer | Number of pods to terminate |
63
+ | `interval` | string | Wait time between terminations |
64
+
65
+ ```javascript
66
+ disruptor.terminatePods({
67
+ count: 1,
68
+ interval: '30s',
69
+ });
70
+ ```
71
+
72
+ ## PodDisruptor
73
+
74
+ Targets pods by label selector.
75
+
76
+ ```javascript
77
+ import { PodDisruptor } from 'k6/x/disruptor';
78
+
79
+ const disruptor = new PodDisruptor({
80
+ namespace: 'default',
81
+ select: {
82
+ labels: { app: 'my-app', version: 'v1' },
83
+ },
84
+ });
85
+ ```
86
+
87
+ Same methods as ServiceDisruptor: `injectHTTPFaults()`, `injectGrpcFaults()`, `terminatePods()`.
88
+
89
+ Additional method:
90
+
91
+ ### targets()
92
+
93
+ Returns list of target pod names:
94
+
95
+ ```javascript
96
+ const pods = disruptor.targets();
97
+ console.log(`Targeting ${pods.length} pods:`, pods);
98
+ ```
99
+
100
+ ## Kubernetes Requirements
101
+
102
+ ### RBAC
103
+
104
+ The k6 pod needs permissions to manage target pods:
105
+
106
+ ```yaml
107
+ apiVersion: rbac.authorization.k8s.io/v1
108
+ kind: ClusterRole
109
+ metadata:
110
+ name: k6-disruptor
111
+ rules:
112
+ - apiGroups: [""]
113
+ resources: ["pods", "pods/ephemeralcontainers"]
114
+ verbs: ["get", "list", "patch", "update", "delete"]
115
+ - apiGroups: [""]
116
+ resources: ["services"]
117
+ verbs: ["get", "list"]
118
+ - apiGroups: ["apps"]
119
+ resources: ["deployments"]
120
+ verbs: ["get", "list"]
121
+ ---
122
+ apiVersion: rbac.authorization.k8s.io/v1
123
+ kind: ClusterRoleBinding
124
+ metadata:
125
+ name: k6-disruptor-binding
126
+ roleRef:
127
+ apiGroup: rbac.authorization.k8s.io
128
+ kind: ClusterRole
129
+ name: k6-disruptor
130
+ subjects:
131
+ - kind: ServiceAccount
132
+ name: default
133
+ namespace: k6-test
134
+ ```
135
+
136
+ ### Running in Cluster
137
+
138
+ For xk6-disruptor to work, k6 must run **inside the Kubernetes cluster** (not locally). Options:
139
+ - k6-operator TestRun
140
+ - Pod with k6 + xk6-disruptor image
141
+ - CI/CD runner with cluster access
142
+
143
+ ## Fault Duration vs Test Duration
144
+
145
+ ```
146
+ Test Duration: |========================== 5 min ============================|
147
+ Fault Duration: |======== 2 min ========|
148
+ ↑ Fault injected ↑ Fault removed ↑ Test ends
149
+
150
+ Phases: |--- Chaos Phase ------|--- Recovery Phase ---|
151
+ ```
152
+
153
+ Set fault duration shorter than test duration to observe both degradation and recovery.