agentic-qe 2.0.0 → 2.1.1

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 (144) hide show
  1. package/.claude/agents/qx-partner.md +17 -4
  2. package/.claude/skills/accessibility-testing/SKILL.md +144 -692
  3. package/.claude/skills/agentic-quality-engineering/SKILL.md +176 -529
  4. package/.claude/skills/api-testing-patterns/SKILL.md +180 -560
  5. package/.claude/skills/brutal-honesty-review/SKILL.md +113 -603
  6. package/.claude/skills/bug-reporting-excellence/SKILL.md +116 -517
  7. package/.claude/skills/chaos-engineering-resilience/SKILL.md +127 -72
  8. package/.claude/skills/cicd-pipeline-qe-orchestrator/SKILL.md +209 -404
  9. package/.claude/skills/code-review-quality/SKILL.md +158 -608
  10. package/.claude/skills/compatibility-testing/SKILL.md +148 -38
  11. package/.claude/skills/compliance-testing/SKILL.md +132 -63
  12. package/.claude/skills/consultancy-practices/SKILL.md +114 -446
  13. package/.claude/skills/context-driven-testing/SKILL.md +117 -381
  14. package/.claude/skills/contract-testing/SKILL.md +176 -141
  15. package/.claude/skills/database-testing/SKILL.md +137 -130
  16. package/.claude/skills/exploratory-testing-advanced/SKILL.md +160 -629
  17. package/.claude/skills/holistic-testing-pact/SKILL.md +140 -188
  18. package/.claude/skills/localization-testing/SKILL.md +145 -33
  19. package/.claude/skills/mobile-testing/SKILL.md +132 -448
  20. package/.claude/skills/mutation-testing/SKILL.md +147 -41
  21. package/.claude/skills/performance-testing/SKILL.md +200 -546
  22. package/.claude/skills/quality-metrics/SKILL.md +164 -519
  23. package/.claude/skills/refactoring-patterns/SKILL.md +132 -699
  24. package/.claude/skills/regression-testing/SKILL.md +120 -926
  25. package/.claude/skills/risk-based-testing/SKILL.md +157 -660
  26. package/.claude/skills/security-testing/SKILL.md +199 -538
  27. package/.claude/skills/sherlock-review/SKILL.md +163 -699
  28. package/.claude/skills/shift-left-testing/SKILL.md +161 -465
  29. package/.claude/skills/shift-right-testing/SKILL.md +161 -519
  30. package/.claude/skills/six-thinking-hats/SKILL.md +175 -1110
  31. package/.claude/skills/skills-manifest.json +71 -20
  32. package/.claude/skills/tdd-london-chicago/SKILL.md +131 -448
  33. package/.claude/skills/technical-writing/SKILL.md +103 -154
  34. package/.claude/skills/test-automation-strategy/SKILL.md +166 -772
  35. package/.claude/skills/test-data-management/SKILL.md +126 -910
  36. package/.claude/skills/test-design-techniques/SKILL.md +179 -89
  37. package/.claude/skills/test-environment-management/SKILL.md +136 -91
  38. package/.claude/skills/test-reporting-analytics/SKILL.md +169 -92
  39. package/.claude/skills/testability-scoring/SKILL.md +172 -538
  40. package/.claude/skills/testability-scoring/scripts/generate-html-report.js +0 -0
  41. package/.claude/skills/visual-testing-advanced/SKILL.md +155 -78
  42. package/.claude/skills/xp-practices/SKILL.md +151 -587
  43. package/CHANGELOG.md +86 -0
  44. package/README.md +23 -16
  45. package/dist/agents/QXPartnerAgent.d.ts +47 -1
  46. package/dist/agents/QXPartnerAgent.d.ts.map +1 -1
  47. package/dist/agents/QXPartnerAgent.js +2086 -125
  48. package/dist/agents/QXPartnerAgent.js.map +1 -1
  49. package/dist/agents/lifecycle/AgentLifecycleManager.d.ts.map +1 -1
  50. package/dist/agents/lifecycle/AgentLifecycleManager.js +34 -31
  51. package/dist/agents/lifecycle/AgentLifecycleManager.js.map +1 -1
  52. package/dist/cli/commands/init-claude-md-template.d.ts.map +1 -1
  53. package/dist/cli/commands/init-claude-md-template.js +14 -0
  54. package/dist/cli/commands/init-claude-md-template.js.map +1 -1
  55. package/dist/core/SwarmCoordinator.d.ts +180 -0
  56. package/dist/core/SwarmCoordinator.d.ts.map +1 -0
  57. package/dist/core/SwarmCoordinator.js +473 -0
  58. package/dist/core/SwarmCoordinator.js.map +1 -0
  59. package/dist/core/memory/ReflexionMemoryAdapter.d.ts +109 -0
  60. package/dist/core/memory/ReflexionMemoryAdapter.d.ts.map +1 -0
  61. package/dist/core/memory/ReflexionMemoryAdapter.js +306 -0
  62. package/dist/core/memory/ReflexionMemoryAdapter.js.map +1 -0
  63. package/dist/core/memory/RuVectorPatternStore.d.ts +28 -0
  64. package/dist/core/memory/RuVectorPatternStore.d.ts.map +1 -1
  65. package/dist/core/memory/RuVectorPatternStore.js +70 -0
  66. package/dist/core/memory/RuVectorPatternStore.js.map +1 -1
  67. package/dist/core/memory/SparseVectorSearch.d.ts +55 -0
  68. package/dist/core/memory/SparseVectorSearch.d.ts.map +1 -0
  69. package/dist/core/memory/SparseVectorSearch.js +130 -0
  70. package/dist/core/memory/SparseVectorSearch.js.map +1 -0
  71. package/dist/core/memory/TieredCompression.d.ts +81 -0
  72. package/dist/core/memory/TieredCompression.d.ts.map +1 -0
  73. package/dist/core/memory/TieredCompression.js +270 -0
  74. package/dist/core/memory/TieredCompression.js.map +1 -0
  75. package/dist/core/memory/index.d.ts +6 -0
  76. package/dist/core/memory/index.d.ts.map +1 -1
  77. package/dist/core/memory/index.js +29 -1
  78. package/dist/core/memory/index.js.map +1 -1
  79. package/dist/core/metrics/MetricsAggregator.d.ts +228 -0
  80. package/dist/core/metrics/MetricsAggregator.d.ts.map +1 -0
  81. package/dist/core/metrics/MetricsAggregator.js +482 -0
  82. package/dist/core/metrics/MetricsAggregator.js.map +1 -0
  83. package/dist/core/metrics/index.d.ts +5 -0
  84. package/dist/core/metrics/index.d.ts.map +1 -0
  85. package/dist/core/metrics/index.js +11 -0
  86. package/dist/core/metrics/index.js.map +1 -0
  87. package/dist/core/optimization/SwarmOptimizer.d.ts +5 -0
  88. package/dist/core/optimization/SwarmOptimizer.d.ts.map +1 -1
  89. package/dist/core/optimization/SwarmOptimizer.js +17 -0
  90. package/dist/core/optimization/SwarmOptimizer.js.map +1 -1
  91. package/dist/core/orchestration/AdaptiveScheduler.d.ts +190 -0
  92. package/dist/core/orchestration/AdaptiveScheduler.d.ts.map +1 -0
  93. package/dist/core/orchestration/AdaptiveScheduler.js +460 -0
  94. package/dist/core/orchestration/AdaptiveScheduler.js.map +1 -0
  95. package/dist/core/orchestration/WorkflowOrchestrator.d.ts +13 -0
  96. package/dist/core/orchestration/WorkflowOrchestrator.d.ts.map +1 -1
  97. package/dist/core/orchestration/WorkflowOrchestrator.js +32 -0
  98. package/dist/core/orchestration/WorkflowOrchestrator.js.map +1 -1
  99. package/dist/core/recovery/CircuitBreaker.d.ts +176 -0
  100. package/dist/core/recovery/CircuitBreaker.d.ts.map +1 -0
  101. package/dist/core/recovery/CircuitBreaker.js +382 -0
  102. package/dist/core/recovery/CircuitBreaker.js.map +1 -0
  103. package/dist/core/recovery/RecoveryOrchestrator.d.ts +186 -0
  104. package/dist/core/recovery/RecoveryOrchestrator.d.ts.map +1 -0
  105. package/dist/core/recovery/RecoveryOrchestrator.js +476 -0
  106. package/dist/core/recovery/RecoveryOrchestrator.js.map +1 -0
  107. package/dist/core/recovery/RetryStrategy.d.ts +127 -0
  108. package/dist/core/recovery/RetryStrategy.d.ts.map +1 -0
  109. package/dist/core/recovery/RetryStrategy.js +314 -0
  110. package/dist/core/recovery/RetryStrategy.js.map +1 -0
  111. package/dist/core/recovery/index.d.ts +8 -0
  112. package/dist/core/recovery/index.d.ts.map +1 -0
  113. package/dist/core/recovery/index.js +27 -0
  114. package/dist/core/recovery/index.js.map +1 -0
  115. package/dist/core/skills/DependencyResolver.d.ts +99 -0
  116. package/dist/core/skills/DependencyResolver.d.ts.map +1 -0
  117. package/dist/core/skills/DependencyResolver.js +260 -0
  118. package/dist/core/skills/DependencyResolver.js.map +1 -0
  119. package/dist/core/skills/ManifestGenerator.d.ts +114 -0
  120. package/dist/core/skills/ManifestGenerator.d.ts.map +1 -0
  121. package/dist/core/skills/ManifestGenerator.js +449 -0
  122. package/dist/core/skills/ManifestGenerator.js.map +1 -0
  123. package/dist/core/skills/index.d.ts +9 -0
  124. package/dist/core/skills/index.d.ts.map +1 -0
  125. package/dist/core/skills/index.js +24 -0
  126. package/dist/core/skills/index.js.map +1 -0
  127. package/dist/mcp/handlers/chaos/chaos-inject-failure.d.ts +5 -0
  128. package/dist/mcp/handlers/chaos/chaos-inject-failure.d.ts.map +1 -1
  129. package/dist/mcp/handlers/chaos/chaos-inject-failure.js +36 -2
  130. package/dist/mcp/handlers/chaos/chaos-inject-failure.js.map +1 -1
  131. package/dist/mcp/handlers/chaos/chaos-inject-latency.d.ts +5 -0
  132. package/dist/mcp/handlers/chaos/chaos-inject-latency.d.ts.map +1 -1
  133. package/dist/mcp/handlers/chaos/chaos-inject-latency.js +36 -2
  134. package/dist/mcp/handlers/chaos/chaos-inject-latency.js.map +1 -1
  135. package/dist/mcp/server.d.ts +9 -9
  136. package/dist/mcp/server.d.ts.map +1 -1
  137. package/dist/mcp/server.js +1 -2
  138. package/dist/mcp/server.js.map +1 -1
  139. package/dist/types/qx.d.ts +113 -7
  140. package/dist/types/qx.d.ts.map +1 -1
  141. package/dist/types/qx.js.map +1 -1
  142. package/dist/visualization/api/RestEndpoints.js +1 -1
  143. package/dist/visualization/api/RestEndpoints.js.map +1 -1
  144. package/package.json +15 -54
@@ -1,42 +1,92 @@
1
1
  ---
2
2
  name: api-testing-patterns
3
- description: Apply comprehensive API testing patterns including contract testing, REST/GraphQL testing, and integration testing. Use when testing APIs, microservices, or designing API test strategies.
3
+ description: "Comprehensive API testing patterns including contract testing, REST/GraphQL testing, and integration testing. Use when testing APIs or designing API test strategies."
4
+ category: testing-methodologies
5
+ priority: high
6
+ tokenEstimate: 1200
7
+ agents: [qe-api-contract-validator, qe-test-generator, qe-performance-tester, qe-security-scanner]
8
+ implementation_status: optimized
9
+ optimization_version: 1.0
10
+ last_optimized: 2025-12-02
11
+ dependencies: []
12
+ quick_reference_card: true
13
+ tags: [api, rest, graphql, contract-testing, pact, integration, microservices]
4
14
  ---
5
15
 
6
16
  # API Testing Patterns
7
17
 
8
- ## Core Principles
18
+ <default_to_action>
19
+ When testing APIs or designing API test strategy:
20
+ 1. IDENTIFY testing level: contract, integration, or component
21
+ 2. TEST the contract, not implementation (consumer perspective)
22
+ 3. VALIDATE auth, input, errors, idempotency, concurrency
23
+ 4. AUTOMATE in CI/CD with schema validation
24
+ 5. MONITOR production APIs for contract drift
25
+
26
+ **Quick Pattern Selection:**
27
+ - Microservices → Consumer-driven contracts (Pact)
28
+ - REST APIs → CRUD + pagination + filtering tests
29
+ - GraphQL → Query validation + complexity limits
30
+ - External deps → Mock with component testing
31
+ - Performance → Load test critical endpoints
32
+
33
+ **Critical Success Factors:**
34
+ - APIs are contracts - test from consumer perspective
35
+ - Always test error scenarios, not just happy paths
36
+ - Version your API tests to prevent breaking changes
37
+ </default_to_action>
38
+
39
+ ## Quick Reference Card
40
+
41
+ ### When to Use
42
+ - Testing REST or GraphQL APIs
43
+ - Validating microservice contracts
44
+ - Designing API test strategies
45
+ - Preventing breaking API changes
46
+
47
+ ### Testing Levels
48
+ | Level | Purpose | Dependencies | Speed |
49
+ |-------|---------|--------------|-------|
50
+ | Contract | Provider-consumer agreement | None | Fast |
51
+ | Component | API in isolation | Mocked | Fast |
52
+ | Integration | Real dependencies | Database, services | Slower |
53
+
54
+ ### Critical Test Scenarios
55
+ | Scenario | Must Test | Example |
56
+ |----------|----------|---------|
57
+ | Auth | 401/403 handling | Expired token, wrong user |
58
+ | Input | 400 validation | Missing fields, wrong types |
59
+ | Errors | 500 graceful handling | DB down, timeout |
60
+ | Idempotency | Duplicate prevention | Same idempotency key |
61
+ | Concurrency | Race conditions | Parallel checkout |
62
+
63
+ ### Tools
64
+ - **Contract**: Pact, Spring Cloud Contract
65
+ - **REST**: Supertest, REST-assured, Playwright
66
+ - **Load**: k6, Artillery, JMeter
67
+
68
+ ### Agent Coordination
69
+ - `qe-api-contract-validator`: Validate contracts, detect breaking changes
70
+ - `qe-test-generator`: Generate tests from OpenAPI spec
71
+ - `qe-performance-tester`: Load test endpoints
72
+ - `qe-security-scanner`: API security testing
9
73
 
10
- APIs are contracts. Test the contract, not the implementation. Focus on behavior from the consumer's perspective, not the provider's internals.
11
-
12
- ## Testing Levels
13
-
14
- ### 1. Contract Testing
74
+ ---
15
75
 
16
- **Purpose:** Verify API provider and consumer agree on the contract.
76
+ ## Contract Testing
17
77
 
18
78
  **Pattern: Consumer-Driven Contracts**
19
79
  ```javascript
20
80
  // Consumer defines expectations
21
- const expectedContract = {
22
- request: {
23
- method: 'POST',
24
- path: '/orders',
25
- body: { productId: 'abc', quantity: 2 }
26
- },
27
- response: {
28
- status: 201,
29
- body: { orderId: 'string', total: 'number' }
30
- }
81
+ const contract = {
82
+ request: { method: 'POST', path: '/orders', body: { productId: 'abc', quantity: 2 } },
83
+ response: { status: 201, body: { orderId: 'string', total: 'number' } }
31
84
  };
32
85
 
33
- // Provider must fulfill this contract
34
- test('order API meets consumer contract', async () => {
35
- const response = await api.post('/orders', {
36
- productId: 'abc',
37
- quantity: 2
38
- });
39
-
86
+ // Provider must fulfill
87
+ test('order API meets contract', async () => {
88
+ const response = await api.post('/orders', { productId: 'abc', quantity: 2 });
89
+
40
90
  expect(response.status).toBe(201);
41
91
  expect(response.body).toMatchSchema({
42
92
  orderId: expect.any(String),
@@ -45,534 +95,180 @@ test('order API meets consumer contract', async () => {
45
95
  });
46
96
  ```
47
97
 
48
- **Tools:** Pact, Spring Cloud Contract
98
+ **When:** Microservices, distributed systems, third-party integrations
49
99
 
50
- **When to use:** Microservices, distributed systems, third-party integrations
51
-
52
- ### 2. Integration Testing
100
+ ---
53
101
 
54
- **Purpose:** Verify API works with real dependencies (database, external services).
102
+ ## Critical Test Patterns
55
103
 
56
- **Pattern: Test with Real Dependencies**
104
+ ### Authentication & Authorization
57
105
  ```javascript
58
- describe('Order API integration', () => {
59
- beforeEach(async () => {
60
- await db.migrate();
61
- await db.seed();
62
- });
63
-
64
- afterEach(async () => {
65
- await db.rollback();
106
+ describe('Auth', () => {
107
+ it('rejects without token', async () => {
108
+ expect((await api.get('/orders')).status).toBe(401);
66
109
  });
67
-
68
- it('creates order and updates inventory', async () => {
69
- const response = await api.post('/orders', {
70
- productId: 'product-123',
71
- quantity: 2
72
- });
73
-
74
- expect(response.status).toBe(201);
75
-
76
- // Verify side effects
77
- const inventory = await db.inventory.findById('product-123');
78
- expect(inventory.quantity).toBe(8); // Was 10, now 8
79
- });
80
- });
81
- ```
82
-
83
- **When to use:** Testing business logic that spans multiple components
84
110
 
85
- ### 3. Component Testing
86
-
87
- **Purpose:** Test API in isolation with mocked dependencies.
88
-
89
- **Pattern: Mock External Dependencies**
90
- ```javascript
91
- describe('Order API component', () => {
92
- it('handles payment service timeout', async () => {
93
- const paymentService = mockPaymentService({
94
- charge: () => { throw new TimeoutError(); }
95
- });
96
-
97
- const api = createAPI({ paymentService });
98
- const response = await api.post('/orders', orderData);
99
-
100
- expect(response.status).toBe(503);
101
- expect(response.body.error).toBe('Payment service unavailable');
111
+ it('rejects expired token', async () => {
112
+ const expired = generateExpiredToken();
113
+ expect((await api.get('/orders', { headers: { Authorization: `Bearer ${expired}` } })).status).toBe(401);
102
114
  });
103
- });
104
- ```
105
-
106
- **When to use:** Testing error handling, edge cases, without hitting real services
107
-
108
- ## Critical Test Scenarios
109
-
110
- ### Authentication & Authorization
111
115
 
112
- ```javascript
113
- describe('Authentication', () => {
114
- it('rejects requests without token', async () => {
115
- const response = await api.get('/orders');
116
- expect(response.status).toBe(401);
117
- });
118
-
119
- it('rejects requests with expired token', async () => {
120
- const expiredToken = generateExpiredToken();
121
- const response = await api.get('/orders', {
122
- headers: { Authorization: `Bearer ${expiredToken}` }
123
- });
124
- expect(response.status).toBe(401);
125
- });
126
-
127
- it('allows access only to authorized resources', async () => {
116
+ it('blocks cross-user access', async () => {
128
117
  const userAToken = generateToken({ userId: 'A' });
129
- const response = await api.get('/orders/user-B-order', {
130
- headers: { Authorization: `Bearer ${userAToken}` }
131
- });
132
- expect(response.status).toBe(403);
118
+ expect((await api.get('/orders/user-B-order', { headers: { Authorization: `Bearer ${userAToken}` } })).status).toBe(403);
133
119
  });
134
120
  });
135
121
  ```
136
122
 
137
123
  ### Input Validation
138
-
139
124
  ```javascript
140
- describe('Input validation', () => {
125
+ describe('Validation', () => {
141
126
  it('validates required fields', async () => {
142
- const response = await api.post('/orders', {
143
- // Missing productId
144
- quantity: 2
145
- });
127
+ const response = await api.post('/orders', { quantity: 2 }); // Missing productId
146
128
  expect(response.status).toBe(400);
147
129
  expect(response.body.errors).toContain('productId is required');
148
130
  });
149
-
150
- it('validates data types', async () => {
151
- const response = await api.post('/orders', {
152
- productId: 'abc',
153
- quantity: 'two' // Should be number
154
- });
155
- expect(response.status).toBe(400);
156
- });
157
-
158
- it('validates value ranges', async () => {
159
- const response = await api.post('/orders', {
160
- productId: 'abc',
161
- quantity: -5 // Negative quantity
162
- });
163
- expect(response.status).toBe(400);
164
- });
165
- });
166
- ```
167
131
 
168
- ### Error Handling
169
-
170
- ```javascript
171
- describe('Error handling', () => {
172
- it('handles database connection failure', async () => {
173
- db.disconnect();
174
- const response = await api.get('/orders');
175
- expect(response.status).toBe(503);
176
- expect(response.body.error).toMatch(/service unavailable/i);
132
+ it('validates types', async () => {
133
+ expect((await api.post('/orders', { productId: 'abc', quantity: 'two' })).status).toBe(400);
177
134
  });
178
-
179
- it('handles malformed JSON', async () => {
180
- const response = await fetch('/orders', {
181
- method: 'POST',
182
- body: 'not-json'
183
- });
184
- expect(response.status).toBe(400);
185
- });
186
-
187
- it('handles unexpected errors gracefully', async () => {
188
- // Simulate internal error
189
- orderService.create = () => { throw new Error('Unexpected'); };
190
-
191
- const response = await api.post('/orders', validOrder);
192
- expect(response.status).toBe(500);
193
- expect(response.body.error).not.toContain('Unexpected'); // Don't leak internals
135
+
136
+ it('validates ranges', async () => {
137
+ expect((await api.post('/orders', { productId: 'abc', quantity: -5 })).status).toBe(400);
194
138
  });
195
139
  });
196
140
  ```
197
141
 
198
142
  ### Idempotency
199
-
200
143
  ```javascript
201
- describe('Idempotent operations', () => {
202
- it('PUT is idempotent', async () => {
203
- const updateData = { status: 'shipped' };
204
-
205
- await api.put('/orders/123', updateData);
206
- const response = await api.put('/orders/123', updateData);
207
-
208
- expect(response.status).toBe(200);
209
- // Verify state hasn't changed incorrectly
210
- });
211
-
212
- it('POST with idempotency key prevents duplicates', async () => {
213
- const idempotencyKey = 'unique-key-123';
214
- const orderData = { productId: 'abc', quantity: 2 };
215
-
216
- const response1 = await api.post('/orders', orderData, {
217
- headers: { 'Idempotency-Key': idempotencyKey }
218
- });
219
-
220
- const response2 = await api.post('/orders', orderData, {
221
- headers: { 'Idempotency-Key': idempotencyKey }
222
- });
223
-
224
- expect(response1.body.orderId).toBe(response2.body.orderId);
225
- // Verify only one order was created
226
- });
144
+ it('prevents duplicates with idempotency key', async () => {
145
+ const key = 'unique-123';
146
+ const data = { productId: 'abc', quantity: 2 };
147
+
148
+ const r1 = await api.post('/orders', data, { headers: { 'Idempotency-Key': key } });
149
+ const r2 = await api.post('/orders', data, { headers: { 'Idempotency-Key': key } });
150
+
151
+ expect(r1.body.orderId).toBe(r2.body.orderId); // Same order
227
152
  });
228
153
  ```
229
154
 
230
155
  ### Concurrency
231
-
232
156
  ```javascript
233
- describe('Concurrent requests', () => {
234
- it('handles race condition on inventory update', async () => {
235
- const promises = Array(10).fill().map(() =>
236
- api.post('/orders', { productId: 'abc', quantity: 1 })
237
- );
238
-
239
- const responses = await Promise.all(promises);
240
- const successful = responses.filter(r => r.status === 201);
241
-
242
- // Verify inventory wasn't oversold
243
- const inventory = await db.inventory.findById('abc');
244
- expect(inventory.quantity).toBe(initialQuantity - successful.length);
245
- });
157
+ it('handles race condition on inventory', async () => {
158
+ const promises = Array(10).fill().map(() =>
159
+ api.post('/orders', { productId: 'abc', quantity: 1 })
160
+ );
161
+ const responses = await Promise.all(promises);
162
+ const successful = responses.filter(r => r.status === 201);
163
+
164
+ const inventory = await db.inventory.findById('abc');
165
+ expect(inventory.quantity).toBe(initialQuantity - successful.length);
246
166
  });
247
167
  ```
248
168
 
249
- ## REST API Testing Patterns
250
-
251
- ### CRUD Operations
169
+ ---
252
170
 
171
+ ## REST CRUD Pattern
253
172
  ```javascript
254
173
  describe('Product CRUD', () => {
255
174
  let productId;
256
-
257
- it('CREATE: creates new product', async () => {
258
- const response = await api.post('/products', {
259
- name: 'Widget',
260
- price: 10.00
261
- });
262
- expect(response.status).toBe(201);
263
- expect(response.headers.location).toMatch(/\/products\/\w+/);
264
- productId = response.body.id;
265
- });
266
-
267
- it('READ: retrieves product', async () => {
268
- const response = await api.get(`/products/${productId}`);
269
- expect(response.status).toBe(200);
270
- expect(response.body.name).toBe('Widget');
271
- });
272
-
273
- it('UPDATE: modifies product', async () => {
274
- const response = await api.put(`/products/${productId}`, {
275
- name: 'Widget',
276
- price: 12.00
277
- });
278
- expect(response.status).toBe(200);
279
- expect(response.body.price).toBe(12.00);
280
- });
281
-
282
- it('DELETE: removes product', async () => {
283
- const response = await api.delete(`/products/${productId}`);
284
- expect(response.status).toBe(204);
285
-
286
- const getResponse = await api.get(`/products/${productId}`);
287
- expect(getResponse.status).toBe(404);
288
- });
289
- });
290
- ```
291
-
292
- ### Pagination
293
175
 
294
- ```javascript
295
- describe('Pagination', () => {
296
- it('returns first page by default', async () => {
297
- const response = await api.get('/products');
298
- expect(response.body.items).toHaveLength(20); // Default page size
299
- expect(response.body.page).toBe(1);
300
- });
301
-
302
- it('supports custom page size', async () => {
303
- const response = await api.get('/products?pageSize=50');
304
- expect(response.body.items).toHaveLength(50);
305
- });
306
-
307
- it('includes pagination metadata', async () => {
308
- const response = await api.get('/products');
309
- expect(response.body).toHaveProperty('totalItems');
310
- expect(response.body).toHaveProperty('totalPages');
311
- expect(response.body).toHaveProperty('nextPage');
176
+ it('CREATE', async () => {
177
+ const r = await api.post('/products', { name: 'Widget', price: 10 });
178
+ expect(r.status).toBe(201);
179
+ productId = r.body.id;
312
180
  });
313
- });
314
- ```
315
181
 
316
- ### Filtering & Sorting
317
-
318
- ```javascript
319
- describe('Filtering and sorting', () => {
320
- it('filters by category', async () => {
321
- const response = await api.get('/products?category=electronics');
322
- expect(response.body.items.every(p => p.category === 'electronics')).toBe(true);
182
+ it('READ', async () => {
183
+ const r = await api.get(`/products/${productId}`);
184
+ expect(r.body.name).toBe('Widget');
323
185
  });
324
-
325
- it('sorts by price ascending', async () => {
326
- const response = await api.get('/products?sort=price:asc');
327
- const prices = response.body.items.map(p => p.price);
328
- expect(prices).toEqual([...prices].sort((a, b) => a - b));
329
- });
330
-
331
- it('combines multiple filters', async () => {
332
- const response = await api.get('/products?category=electronics&minPrice=100');
333
- expect(response.body.items.every(p =>
334
- p.category === 'electronics' && p.price >= 100
335
- )).toBe(true);
336
- });
337
- });
338
- ```
339
186
 
340
- ## GraphQL Testing Patterns
341
-
342
- ```javascript
343
- describe('GraphQL API', () => {
344
- it('queries nested data', async () => {
345
- const query = `
346
- query {
347
- order(id: "123") {
348
- id
349
- items {
350
- product {
351
- name
352
- price
353
- }
354
- quantity
355
- }
356
- total
357
- }
358
- }
359
- `;
360
-
361
- const response = await graphql.query(query);
362
- expect(response.data.order.items).toBeDefined();
187
+ it('UPDATE', async () => {
188
+ const r = await api.put(`/products/${productId}`, { price: 12 });
189
+ expect(r.body.price).toBe(12);
363
190
  });
364
-
365
- it('handles query complexity limits', async () => {
366
- const complexQuery = `
367
- query {
368
- orders {
369
- items {
370
- product {
371
- reviews {
372
- author {
373
- orders { ... }
374
- }
375
- }
376
- }
377
- }
378
- }
379
- }
380
- `;
381
-
382
- const response = await graphql.query(complexQuery);
383
- expect(response.errors[0].message).toMatch(/query too complex/i);
384
- });
385
- });
386
- ```
387
-
388
- ## Performance Testing
389
191
 
390
- ```javascript
391
- describe('API performance', () => {
392
- it('responds within acceptable time', async () => {
393
- const start = Date.now();
394
- await api.get('/products');
395
- const duration = Date.now() - start;
396
-
397
- expect(duration).toBeLessThan(200); // 200ms SLA
398
- });
399
-
400
- it('handles load of 100 concurrent requests', async () => {
401
- const requests = Array(100).fill().map(() => api.get('/products'));
402
- const responses = await Promise.all(requests);
403
-
404
- const successful = responses.filter(r => r.status === 200);
405
- expect(successful.length).toBeGreaterThan(95); // 95% success rate
192
+ it('DELETE', async () => {
193
+ expect((await api.delete(`/products/${productId}`)).status).toBe(204);
194
+ expect((await api.get(`/products/${productId}`)).status).toBe(404);
406
195
  });
407
196
  });
408
197
  ```
409
198
 
410
- ## Testing Tools
411
-
412
- ### REST APIs
413
- - **Supertest** (Node.js) - HTTP assertions
414
- - **REST-assured** (Java) - Fluent API testing
415
- - **Postman/Newman** - Collection-based testing
416
- - **Playwright API** - E2E with API calls
417
-
418
- ### Contract Testing
419
- - **Pact** - Consumer-driven contracts
420
- - **Spring Cloud Contract** - JVM contract testing
421
-
422
- ### Load Testing
423
- - **k6** - Modern load testing
424
- - **Apache JMeter** - Enterprise load testing
425
- - **Artillery** - Modern performance testing
426
-
427
- ## Common Pitfalls
428
-
429
- ### ❌ Testing Implementation, Not Contract
430
- Don't test internal database queries. Test the API response.
431
-
432
- ### ❌ Ignoring HTTP Semantics
433
- Use correct status codes (200, 201, 400, 404, 500) and methods (GET, POST, PUT, DELETE).
434
-
435
- ### ❌ No Negative Testing
436
- Always test error cases, not just happy paths.
437
-
438
- ### ❌ Brittle Tests
439
- Don't assert on field order or extra fields. Focus on contract.
440
-
441
- ### ❌ Slow Tests
442
- Mock external services. Don't wait for real third-party APIs.
199
+ ---
443
200
 
444
201
  ## Best Practices
445
202
 
446
- ### ✅ Test from Consumer Perspective
447
- Write tests as if you're using the API, not implementing it.
448
-
449
- ### Use Schema Validation
450
- Validate response structure, not exact values.
451
-
452
- ### ✅ Test Error Scenarios
453
- Network failures, timeouts, invalid input, authorization errors.
454
-
455
- ### ✅ Version Your API Tests
456
- Keep tests for each API version to prevent breaking changes.
203
+ ### ✅ Do This
204
+ - Test from consumer perspective
205
+ - Use schema validation (not exact values)
206
+ - Test error scenarios extensively
207
+ - Version API tests
208
+ - Automate in CI/CD
457
209
 
458
- ### Automate in CI/CD
459
- Run API tests on every commit, not just before release.
210
+ ### Avoid This
211
+ - Testing implementation, not contract
212
+ - Ignoring HTTP semantics (status codes)
213
+ - No negative testing
214
+ - Asserting on field order or extra fields
215
+ - Slow tests (mock external services)
460
216
 
461
- ## Real-World Example: E-Commerce API
462
-
463
- ```javascript
464
- describe('E-Commerce Order API', () => {
465
- describe('Happy path', () => {
466
- it('complete order flow', async () => {
467
- // Add to cart
468
- const cart = await api.post('/cart', { productId: 'abc', quantity: 2 });
469
-
470
- // Apply discount
471
- await api.post('/cart/discount', { code: 'SAVE10' });
472
-
473
- // Checkout
474
- const order = await api.post('/orders', {
475
- cartId: cart.body.id,
476
- payment: { method: 'card', token: 'tok_123' }
477
- });
478
-
479
- expect(order.status).toBe(201);
480
- expect(order.body.status).toBe('pending');
481
- });
482
- });
483
-
484
- describe('Edge cases', () => {
485
- it('handles out of stock during checkout', async () => {
486
- // Product sold out between cart and checkout
487
- const order = await api.post('/orders', {
488
- cartId: 'cart-with-sold-out-item'
489
- });
490
-
491
- expect(order.status).toBe(409); // Conflict
492
- expect(order.body.error).toMatch(/out of stock/i);
493
- });
494
- });
495
- });
496
- ```
497
-
498
- ## Using with QE Agents
217
+ ---
499
218
 
500
- ### Automated Contract Testing
219
+ ## Agent-Assisted API Testing
501
220
 
502
- **qe-api-contract-validator** ensures API contracts are maintained:
503
221
  ```typescript
504
- // Agent validates API contract against specification
505
- await agent.validateContract({
222
+ // Validate contracts
223
+ await Task("Contract Validation", {
506
224
  spec: 'openapi.yaml',
507
225
  endpoint: '/orders',
508
- method: 'POST',
509
226
  checkBreakingChanges: true
510
- });
227
+ }, "qe-api-contract-validator");
511
228
 
512
- // Returns:
513
- // {
514
- // valid: false,
515
- // breakingChanges: [
516
- // 'Field "orderId" changed from string to number'
517
- // ],
518
- // warnings: ['New optional field "metadata" added']
519
- // }
520
- ```
521
-
522
- ### Agent-Generated API Test Suites
523
-
524
- **qe-test-generator** creates comprehensive API tests:
525
- ```typescript
526
- // Generate tests from OpenAPI spec
527
- await agent.generateFromSpec({
229
+ // Generate tests from spec
230
+ await Task("Generate API Tests", {
528
231
  spec: 'openapi.yaml',
529
232
  coverage: 'comprehensive',
530
- include: [
531
- 'happy-paths',
532
- 'input-validation',
533
- 'auth-scenarios',
534
- 'error-handling',
535
- 'idempotency',
536
- 'concurrency'
537
- ]
538
- });
233
+ include: ['happy-paths', 'input-validation', 'auth-scenarios', 'error-handling']
234
+ }, "qe-test-generator");
235
+
236
+ // Load test
237
+ await Task("API Load Test", {
238
+ endpoint: '/orders',
239
+ rps: 1000,
240
+ duration: '5min'
241
+ }, "qe-performance-tester");
539
242
 
540
- // Creates 200+ tests covering all API patterns
243
+ // Security scan
244
+ await Task("API Security Scan", {
245
+ spec: 'openapi.yaml',
246
+ checks: ['sql-injection', 'xss', 'broken-auth', 'rate-limiting']
247
+ }, "qe-security-scanner");
541
248
  ```
542
249
 
543
- ### Real-Time API Test Execution
250
+ ---
544
251
 
545
- **qe-test-executor** runs API tests with smart retry logic:
546
- ```typescript
547
- // Execute API tests with intelligent retry for flakiness
548
- await agent.executeAPITests({
549
- suite: 'integration',
550
- parallel: true,
551
- retryStrategy: 'exponential-backoff',
552
- flakyDetection: true
553
- });
252
+ ## Agent Coordination Hints
554
253
 
555
- // Detects and reports network-related flakiness
556
- // → Auto-retries transient failures (503, timeout)
557
- // → Fails fast on persistent errors (401, 404)
254
+ ### Memory Namespace
255
+ ```
256
+ aqe/api-testing/
257
+ ├── contracts/* - API contract definitions
258
+ ├── generated-tests/* - Generated test suites
259
+ ├── validation/* - Contract validation results
260
+ └── performance/* - Load test results
558
261
  ```
559
262
 
560
- ### Contract-Based Integration Testing
561
-
263
+ ### Fleet Coordination
562
264
  ```typescript
563
- // Agent coordinates contract testing between services
564
- const contractFleet = await FleetManager.coordinate({
265
+ const apiFleet = await FleetManager.coordinate({
565
266
  strategy: 'contract-testing',
566
- agents: [
567
- 'qe-api-contract-validator', // Validate contracts
568
- 'qe-test-generator', // Generate consumer tests
569
- 'qe-test-executor' // Execute against provider
570
- ],
571
- topology: 'mesh' // Consumer-provider pairs
267
+ agents: ['qe-api-contract-validator', 'qe-test-generator', 'qe-test-executor'],
268
+ topology: 'mesh'
572
269
  });
573
270
 
574
- // Microservices contract validation
575
- await contractFleet.execute({
271
+ await apiFleet.execute({
576
272
  services: [
577
273
  { name: 'orders-api', consumers: ['checkout-ui', 'admin-api'] },
578
274
  { name: 'payment-api', consumers: ['orders-api'] }
@@ -580,95 +276,19 @@ await contractFleet.execute({
580
276
  });
581
277
  ```
582
278
 
583
- ### Performance Testing for APIs
584
-
585
- **qe-performance-tester** load tests critical endpoints:
586
- ```typescript
587
- // Agent runs load tests on API endpoints
588
- await agent.loadTest({
589
- endpoint: '/orders',
590
- method: 'POST',
591
- rps: 1000, // 1000 requests per second
592
- duration: '5min',
593
- scenarios: [
594
- 'create-order',
595
- 'concurrent-checkouts',
596
- 'bulk-operations'
597
- ]
598
- });
599
-
600
- // Returns:
601
- // {
602
- // avgResponseTime: '45ms',
603
- // p95: '120ms',
604
- // p99: '250ms',
605
- // errorRate: 0.02, // 2% error rate
606
- // bottlenecks: ['database connection pool']
607
- // }
608
- ```
609
-
610
- ### Security Testing for APIs
611
-
612
- **qe-security-scanner** tests API vulnerabilities:
613
- ```typescript
614
- // Agent scans for API security issues
615
- await agent.scanAPI({
616
- spec: 'openapi.yaml',
617
- checks: [
618
- 'sql-injection',
619
- 'xss',
620
- 'broken-auth',
621
- 'excessive-data-exposure',
622
- 'rate-limiting',
623
- 'input-validation'
624
- ]
625
- });
626
-
627
- // Identifies:
628
- // - Missing rate limiting on /login
629
- // - No input sanitization on /search
630
- // - Exposed internal IDs in responses
631
- ```
632
-
633
- ### Continuous Contract Monitoring
634
-
635
- **qe-production-intelligence** monitors live API contracts:
636
- ```typescript
637
- // Agent monitors production API for contract drift
638
- await agent.monitorAPIContract({
639
- endpoint: '/orders',
640
- spec: 'openapi.yaml',
641
- alertOn: 'breaking-changes',
642
- sampleRate: 0.01 // Monitor 1% of traffic
643
- });
644
-
645
- // Alerts:
646
- // "⚠️ Production API returning extra field not in spec: 'internalProcessId'"
647
- // "🔴 Breaking change detected: 'quantity' changed from int to string"
648
- ```
649
-
650
279
  ---
651
280
 
652
281
  ## Related Skills
653
-
654
- **Core Quality Practices:**
655
- - [agentic-quality-engineering](../agentic-quality-engineering/) - API testing with agent coordination
656
- - [holistic-testing-pact](../holistic-testing-pact/) - APIs in test quadrants
657
-
658
- **Testing Approaches:**
659
- - [test-automation-strategy](../test-automation-strategy/) - API tests in automation pyramid
660
- - [risk-based-testing](../risk-based-testing/) - Risk-based API test prioritization
661
- - [performance-testing](../performance-testing/) - API load testing patterns
282
+ - [agentic-quality-engineering](../agentic-quality-engineering/) - API testing with agents
283
+ - [tdd-london-chicago](../tdd-london-chicago/) - London school for API testing
284
+ - [performance-testing](../performance-testing/) - API load testing
662
285
  - [security-testing](../security-testing/) - API security validation
663
-
664
- **Development Practices:**
665
- - [tdd-london-chicago](../tdd-london-chicago/) - London school for API testing (mocking)
666
- - [code-review-quality](../code-review-quality/) - Review API test quality
286
+ - [contract-testing](../contract-testing/) - Consumer-driven contracts deep dive
667
287
 
668
288
  ---
669
289
 
670
290
  ## Remember
671
291
 
672
- API testing is about verifying contracts and behavior, not implementation details. Focus on what matters to API consumers: correct responses, proper error handling, and acceptable performance.
292
+ API testing = verifying contracts and behavior, not implementation. Focus on what matters to consumers: correct responses, proper error handling, acceptable performance.
673
293
 
674
- **With Agents**: Agents automate contract validation, generate comprehensive API test suites from specifications, and continuously monitor production APIs for contract drift. Use agents to maintain API quality across microservices at scale.
294
+ **With Agents:** Agents automate contract validation, generate comprehensive test suites from specs, and monitor production APIs for drift. Use agents to maintain API quality at scale.