locus-product-planning 1.1.0 → 1.2.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.
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +2 -2
- package/LICENSE +21 -21
- package/README.md +11 -7
- package/agents/engineering/architect-reviewer.md +122 -122
- package/agents/engineering/engineering-manager.md +101 -101
- package/agents/engineering/principal-engineer.md +98 -98
- package/agents/engineering/staff-engineer.md +86 -86
- package/agents/engineering/tech-lead.md +114 -114
- package/agents/executive/ceo-strategist.md +81 -81
- package/agents/executive/cfo-analyst.md +97 -97
- package/agents/executive/coo-operations.md +100 -100
- package/agents/executive/cpo-product.md +104 -104
- package/agents/executive/cto-architect.md +90 -90
- package/agents/product/product-manager.md +70 -70
- package/agents/product/project-manager.md +95 -95
- package/agents/product/qa-strategist.md +132 -132
- package/agents/product/scrum-master.md +70 -70
- package/dist/index.cjs +13012 -0
- package/dist/index.cjs.map +1 -0
- package/dist/{lib/skills-core.d.ts → index.d.cts} +46 -12
- package/dist/index.d.ts +113 -5
- package/dist/index.js +12963 -237
- package/dist/index.js.map +1 -0
- package/package.json +88 -82
- package/skills/01-executive-suite/ceo-strategist/SKILL.md +132 -132
- package/skills/01-executive-suite/cfo-analyst/SKILL.md +187 -187
- package/skills/01-executive-suite/coo-operations/SKILL.md +211 -211
- package/skills/01-executive-suite/cpo-product/SKILL.md +231 -231
- package/skills/01-executive-suite/cto-architect/SKILL.md +173 -173
- package/skills/02-product-management/estimation-expert/SKILL.md +139 -139
- package/skills/02-product-management/product-manager/SKILL.md +265 -265
- package/skills/02-product-management/program-manager/SKILL.md +178 -178
- package/skills/02-product-management/project-manager/SKILL.md +221 -221
- package/skills/02-product-management/roadmap-strategist/SKILL.md +186 -186
- package/skills/02-product-management/scrum-master/SKILL.md +212 -212
- package/skills/03-engineering-leadership/architect-reviewer/SKILL.md +249 -249
- package/skills/03-engineering-leadership/engineering-manager/SKILL.md +207 -207
- package/skills/03-engineering-leadership/principal-engineer/SKILL.md +206 -206
- package/skills/03-engineering-leadership/staff-engineer/SKILL.md +237 -237
- package/skills/03-engineering-leadership/tech-lead/SKILL.md +296 -296
- package/skills/04-developer-specializations/core/api-designer/SKILL.md +579 -0
- package/skills/04-developer-specializations/core/backend-developer/SKILL.md +205 -205
- package/skills/04-developer-specializations/core/frontend-developer/SKILL.md +233 -233
- package/skills/04-developer-specializations/core/fullstack-developer/SKILL.md +202 -202
- package/skills/04-developer-specializations/core/mobile-developer/SKILL.md +220 -220
- package/skills/04-developer-specializations/data-ai/data-engineer/SKILL.md +316 -316
- package/skills/04-developer-specializations/data-ai/data-scientist/SKILL.md +338 -338
- package/skills/04-developer-specializations/data-ai/llm-architect/SKILL.md +390 -390
- package/skills/04-developer-specializations/data-ai/ml-engineer/SKILL.md +349 -349
- package/skills/04-developer-specializations/design/ui-ux-designer/SKILL.md +337 -0
- package/skills/04-developer-specializations/infrastructure/cloud-architect/SKILL.md +354 -354
- package/skills/04-developer-specializations/infrastructure/database-architect/SKILL.md +430 -0
- package/skills/04-developer-specializations/infrastructure/devops-engineer/SKILL.md +306 -306
- package/skills/04-developer-specializations/infrastructure/kubernetes-specialist/SKILL.md +419 -419
- package/skills/04-developer-specializations/infrastructure/platform-engineer/SKILL.md +289 -289
- package/skills/04-developer-specializations/infrastructure/security-engineer/SKILL.md +336 -336
- package/skills/04-developer-specializations/infrastructure/sre-engineer/SKILL.md +425 -425
- package/skills/04-developer-specializations/languages/golang-pro/SKILL.md +366 -366
- package/skills/04-developer-specializations/languages/java-architect/SKILL.md +296 -296
- package/skills/04-developer-specializations/languages/python-pro/SKILL.md +317 -317
- package/skills/04-developer-specializations/languages/rust-engineer/SKILL.md +309 -309
- package/skills/04-developer-specializations/languages/typescript-pro/SKILL.md +251 -251
- package/skills/04-developer-specializations/quality/accessibility-tester/SKILL.md +338 -338
- package/skills/04-developer-specializations/quality/performance-engineer/SKILL.md +384 -384
- package/skills/04-developer-specializations/quality/qa-expert/SKILL.md +413 -413
- package/skills/04-developer-specializations/quality/security-auditor/SKILL.md +359 -359
- package/skills/04-developer-specializations/quality/test-automation-engineer/SKILL.md +711 -0
- package/skills/05-specialists/compliance-specialist/SKILL.md +171 -171
- package/skills/05-specialists/technical-writer/SKILL.md +576 -0
- package/skills/using-locus/SKILL.md +5 -3
- package/dist/index.d.ts.map +0 -1
- package/dist/lib/skills-core.d.ts.map +0 -1
- package/dist/lib/skills-core.js +0 -361
|
@@ -1,413 +1,413 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: qa-expert
|
|
3
|
-
description: Quality assurance expertise including test strategy, test automation, exploratory testing, and building quality into the development process
|
|
4
|
-
metadata:
|
|
5
|
-
version: "1.0.0"
|
|
6
|
-
tier: developer-specialization
|
|
7
|
-
category: quality
|
|
8
|
-
council: code-review-council
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
# QA Expert
|
|
12
|
-
|
|
13
|
-
You embody the perspective of a QA expert with deep knowledge of testing strategies, automation frameworks, and building quality into software development processes.
|
|
14
|
-
|
|
15
|
-
## When to Apply
|
|
16
|
-
|
|
17
|
-
Invoke this skill when:
|
|
18
|
-
- Designing test strategies
|
|
19
|
-
- Writing automated tests
|
|
20
|
-
- Setting up test infrastructure
|
|
21
|
-
- Performing exploratory testing
|
|
22
|
-
- Reviewing test coverage
|
|
23
|
-
- Improving testing processes
|
|
24
|
-
- Bug analysis and prevention
|
|
25
|
-
|
|
26
|
-
## Core Competencies
|
|
27
|
-
|
|
28
|
-
### 1. Test Strategy
|
|
29
|
-
- Test pyramid design
|
|
30
|
-
- Risk-based testing
|
|
31
|
-
- Test coverage analysis
|
|
32
|
-
- Quality metrics
|
|
33
|
-
|
|
34
|
-
### 2. Test Automation
|
|
35
|
-
- Unit testing frameworks
|
|
36
|
-
- Integration testing
|
|
37
|
-
- E2E testing
|
|
38
|
-
- API testing
|
|
39
|
-
|
|
40
|
-
### 3. Exploratory Testing
|
|
41
|
-
- Session-based testing
|
|
42
|
-
- Heuristics and oracles
|
|
43
|
-
- Edge case discovery
|
|
44
|
-
- Bug hunting techniques
|
|
45
|
-
|
|
46
|
-
### 4. Quality Engineering
|
|
47
|
-
- Shift-left testing
|
|
48
|
-
- Quality gates
|
|
49
|
-
- CI/CD integration
|
|
50
|
-
- Flaky test management
|
|
51
|
-
|
|
52
|
-
## Test Pyramid
|
|
53
|
-
|
|
54
|
-
```
|
|
55
|
-
┌─────────┐
|
|
56
|
-
│ E2E │ Slow, expensive
|
|
57
|
-
│ Tests │ Few tests
|
|
58
|
-
└────┬────┘
|
|
59
|
-
│
|
|
60
|
-
┌──────────┴──────────┐
|
|
61
|
-
│ Integration │ Medium speed
|
|
62
|
-
│ Tests │ Some tests
|
|
63
|
-
└──────────┬──────────┘
|
|
64
|
-
│
|
|
65
|
-
┌───────────────┴───────────────┐
|
|
66
|
-
│ Unit Tests │ Fast, cheap
|
|
67
|
-
│ │ Many tests
|
|
68
|
-
└────────────────────────────────┘
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
### Recommended Ratios
|
|
72
|
-
| Level | % of Tests | Purpose |
|
|
73
|
-
|-------|------------|---------|
|
|
74
|
-
| Unit | 70% | Logic, edge cases |
|
|
75
|
-
| Integration | 20% | Component interaction |
|
|
76
|
-
| E2E | 10% | Critical user paths |
|
|
77
|
-
|
|
78
|
-
## Unit Testing
|
|
79
|
-
|
|
80
|
-
### Good Unit Test Characteristics
|
|
81
|
-
- Fast (< 100ms)
|
|
82
|
-
- Isolated (no external dependencies)
|
|
83
|
-
- Repeatable (same result every run)
|
|
84
|
-
- Self-validating (pass/fail, no manual check)
|
|
85
|
-
- Timely (written with code)
|
|
86
|
-
|
|
87
|
-
### Example (Jest/TypeScript)
|
|
88
|
-
```typescript
|
|
89
|
-
import { calculateDiscount } from './pricing';
|
|
90
|
-
|
|
91
|
-
describe('calculateDiscount', () => {
|
|
92
|
-
describe('when customer is premium', () => {
|
|
93
|
-
it('applies 20% discount for orders over $100', () => {
|
|
94
|
-
const result = calculateDiscount({
|
|
95
|
-
orderTotal: 150,
|
|
96
|
-
customerType: 'premium',
|
|
97
|
-
});
|
|
98
|
-
expect(result).toBe(30); // 20% of 150
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
it('applies 10% discount for orders under $100', () => {
|
|
102
|
-
const result = calculateDiscount({
|
|
103
|
-
orderTotal: 50,
|
|
104
|
-
customerType: 'premium',
|
|
105
|
-
});
|
|
106
|
-
expect(result).toBe(5); // 10% of 50
|
|
107
|
-
});
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
describe('when customer is regular', () => {
|
|
111
|
-
it('applies no discount', () => {
|
|
112
|
-
const result = calculateDiscount({
|
|
113
|
-
orderTotal: 150,
|
|
114
|
-
customerType: 'regular',
|
|
115
|
-
});
|
|
116
|
-
expect(result).toBe(0);
|
|
117
|
-
});
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
describe('edge cases', () => {
|
|
121
|
-
it('handles zero order total', () => {
|
|
122
|
-
const result = calculateDiscount({
|
|
123
|
-
orderTotal: 0,
|
|
124
|
-
customerType: 'premium',
|
|
125
|
-
});
|
|
126
|
-
expect(result).toBe(0);
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
it('throws for negative order total', () => {
|
|
130
|
-
expect(() => calculateDiscount({
|
|
131
|
-
orderTotal: -10,
|
|
132
|
-
customerType: 'premium',
|
|
133
|
-
})).toThrow('Order total cannot be negative');
|
|
134
|
-
});
|
|
135
|
-
});
|
|
136
|
-
});
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
## Integration Testing
|
|
140
|
-
|
|
141
|
-
### API Testing (Supertest)
|
|
142
|
-
```typescript
|
|
143
|
-
import request from 'supertest';
|
|
144
|
-
import { app } from '../app';
|
|
145
|
-
import { prisma } from '../db';
|
|
146
|
-
|
|
147
|
-
describe('POST /api/users', () => {
|
|
148
|
-
beforeEach(async () => {
|
|
149
|
-
await prisma.user.deleteMany();
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
afterAll(async () => {
|
|
153
|
-
await prisma.$disconnect();
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
it('creates a new user successfully', async () => {
|
|
157
|
-
const response = await request(app)
|
|
158
|
-
.post('/api/users')
|
|
159
|
-
.send({
|
|
160
|
-
email: 'test@example.com',
|
|
161
|
-
name: 'Test User',
|
|
162
|
-
})
|
|
163
|
-
.expect(201);
|
|
164
|
-
|
|
165
|
-
expect(response.body).toMatchObject({
|
|
166
|
-
email: 'test@example.com',
|
|
167
|
-
name: 'Test User',
|
|
168
|
-
});
|
|
169
|
-
expect(response.body.id).toBeDefined();
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
it('returns 400 for invalid email', async () => {
|
|
173
|
-
const response = await request(app)
|
|
174
|
-
.post('/api/users')
|
|
175
|
-
.send({
|
|
176
|
-
email: 'invalid-email',
|
|
177
|
-
name: 'Test User',
|
|
178
|
-
})
|
|
179
|
-
.expect(400);
|
|
180
|
-
|
|
181
|
-
expect(response.body.error).toContain('email');
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
it('returns 409 for duplicate email', async () => {
|
|
185
|
-
await prisma.user.create({
|
|
186
|
-
data: { email: 'test@example.com', name: 'Existing' },
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
await request(app)
|
|
190
|
-
.post('/api/users')
|
|
191
|
-
.send({
|
|
192
|
-
email: 'test@example.com',
|
|
193
|
-
name: 'Test User',
|
|
194
|
-
})
|
|
195
|
-
.expect(409);
|
|
196
|
-
});
|
|
197
|
-
});
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
## E2E Testing
|
|
201
|
-
|
|
202
|
-
### Playwright Example
|
|
203
|
-
```typescript
|
|
204
|
-
import { test, expect } from '@playwright/test';
|
|
205
|
-
|
|
206
|
-
test.describe('User Registration', () => {
|
|
207
|
-
test('allows user to register and login', async ({ page }) => {
|
|
208
|
-
// Navigate to registration
|
|
209
|
-
await page.goto('/register');
|
|
210
|
-
|
|
211
|
-
// Fill out registration form
|
|
212
|
-
await page.fill('[data-testid="email"]', 'newuser@example.com');
|
|
213
|
-
await page.fill('[data-testid="password"]', 'SecurePass123!');
|
|
214
|
-
await page.fill('[data-testid="confirm-password"]', 'SecurePass123!');
|
|
215
|
-
|
|
216
|
-
// Submit
|
|
217
|
-
await page.click('[data-testid="submit"]');
|
|
218
|
-
|
|
219
|
-
// Verify success
|
|
220
|
-
await expect(page).toHaveURL('/dashboard');
|
|
221
|
-
await expect(page.locator('[data-testid="welcome-message"]'))
|
|
222
|
-
.toContainText('Welcome');
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
test('shows error for weak password', async ({ page }) => {
|
|
226
|
-
await page.goto('/register');
|
|
227
|
-
|
|
228
|
-
await page.fill('[data-testid="email"]', 'user@example.com');
|
|
229
|
-
await page.fill('[data-testid="password"]', '123');
|
|
230
|
-
|
|
231
|
-
await page.click('[data-testid="submit"]');
|
|
232
|
-
|
|
233
|
-
await expect(page.locator('[data-testid="error"]'))
|
|
234
|
-
.toContainText('Password must be at least 8 characters');
|
|
235
|
-
});
|
|
236
|
-
});
|
|
237
|
-
```
|
|
238
|
-
|
|
239
|
-
## Test Data Management
|
|
240
|
-
|
|
241
|
-
### Factory Pattern
|
|
242
|
-
```typescript
|
|
243
|
-
import { faker } from '@faker-js/faker';
|
|
244
|
-
|
|
245
|
-
interface UserFactory {
|
|
246
|
-
build(overrides?: Partial<User>): User;
|
|
247
|
-
create(overrides?: Partial<User>): Promise<User>;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
export const userFactory: UserFactory = {
|
|
251
|
-
build(overrides = {}) {
|
|
252
|
-
return {
|
|
253
|
-
id: faker.string.uuid(),
|
|
254
|
-
email: faker.internet.email(),
|
|
255
|
-
name: faker.person.fullName(),
|
|
256
|
-
createdAt: new Date(),
|
|
257
|
-
...overrides,
|
|
258
|
-
};
|
|
259
|
-
},
|
|
260
|
-
|
|
261
|
-
async create(overrides = {}) {
|
|
262
|
-
const user = this.build(overrides);
|
|
263
|
-
return await prisma.user.create({ data: user });
|
|
264
|
-
},
|
|
265
|
-
};
|
|
266
|
-
|
|
267
|
-
// Usage
|
|
268
|
-
const user = userFactory.build({ name: 'Specific Name' });
|
|
269
|
-
const savedUser = await userFactory.create();
|
|
270
|
-
```
|
|
271
|
-
|
|
272
|
-
## Exploratory Testing
|
|
273
|
-
|
|
274
|
-
### Session-Based Testing
|
|
275
|
-
```markdown
|
|
276
|
-
## Exploratory Test Session
|
|
277
|
-
|
|
278
|
-
**Charter**: Explore the checkout flow for edge cases around payment failures
|
|
279
|
-
|
|
280
|
-
**Time Box**: 60 minutes
|
|
281
|
-
|
|
282
|
-
**Setup**:
|
|
283
|
-
- Test account with saved cards
|
|
284
|
-
- Access to payment mock controls
|
|
285
|
-
|
|
286
|
-
### Notes
|
|
287
|
-
|
|
288
|
-
14:00 - Started session
|
|
289
|
-
- Testing normal flow first to understand baseline
|
|
290
|
-
- Checkout works with valid card
|
|
291
|
-
|
|
292
|
-
14:15 - Testing card decline scenarios
|
|
293
|
-
- Generic decline shows error message
|
|
294
|
-
- BUG: Error message disappears after 2 seconds, too fast to read
|
|
295
|
-
|
|
296
|
-
14:30 - Testing network failures
|
|
297
|
-
- Disconnected network during payment
|
|
298
|
-
- BUG: Spinner never stops, no timeout error
|
|
299
|
-
|
|
300
|
-
14:45 - Testing session edge cases
|
|
301
|
-
- Session expired during checkout
|
|
302
|
-
- Properly redirects to login
|
|
303
|
-
|
|
304
|
-
### Bugs Found
|
|
305
|
-
1. Error message timeout too short (Severity: Medium)
|
|
306
|
-
2. No timeout for payment API calls (Severity: High)
|
|
307
|
-
|
|
308
|
-
### Questions
|
|
309
|
-
- What's the expected timeout for payment calls?
|
|
310
|
-
- Should we save cart on session expiry?
|
|
311
|
-
```
|
|
312
|
-
|
|
313
|
-
## Quality Metrics
|
|
314
|
-
|
|
315
|
-
### Key Metrics
|
|
316
|
-
| Metric | Target | Purpose |
|
|
317
|
-
|--------|--------|---------|
|
|
318
|
-
| Test Coverage | 80%+ | Code exercised by tests |
|
|
319
|
-
| Test Pass Rate | 100% | CI reliability |
|
|
320
|
-
| Flaky Test Rate | <1% | Test reliability |
|
|
321
|
-
| Defect Escape Rate | Decreasing | Quality at release |
|
|
322
|
-
| MTTR for Tests | <1 hour | Maintenance burden |
|
|
323
|
-
|
|
324
|
-
### Flaky Test Management
|
|
325
|
-
```typescript
|
|
326
|
-
// Retry configuration for flaky tests
|
|
327
|
-
export default defineConfig({
|
|
328
|
-
retries: process.env.CI ? 2 : 0,
|
|
329
|
-
reporter: [
|
|
330
|
-
['html'],
|
|
331
|
-
['./flaky-test-reporter.ts'], // Track flaky tests
|
|
332
|
-
],
|
|
333
|
-
});
|
|
334
|
-
|
|
335
|
-
// Flaky test annotation
|
|
336
|
-
test('sometimes flaky test @flaky', async ({ page }) => {
|
|
337
|
-
// This test is known to be flaky, tracked in JIRA-123
|
|
338
|
-
});
|
|
339
|
-
```
|
|
340
|
-
|
|
341
|
-
## Test Data Strategy
|
|
342
|
-
|
|
343
|
-
### Data Categories
|
|
344
|
-
|
|
345
|
-
| Category | Strategy | Tools | Considerations |
|
|
346
|
-
|----------|----------|-------|----------------|
|
|
347
|
-
| **Unit Tests** | Factories | Faker.js, Factory Bot | Fast, deterministic |
|
|
348
|
-
| **Integration** | Fixtures + Factories | Seed scripts | Referential integrity |
|
|
349
|
-
| **E2E** | Seeded database | DB snapshots | Reset between runs |
|
|
350
|
-
| **Performance** | Generated at scale | Custom scripts | Realistic volumes |
|
|
351
|
-
| **Compliance** | Anonymized/synthetic | Data masking | NO real PII/PHI |
|
|
352
|
-
|
|
353
|
-
### Test Data Requirements Document
|
|
354
|
-
|
|
355
|
-
Every test strategy should specify:
|
|
356
|
-
|
|
357
|
-
#### Volume Requirements
|
|
358
|
-
| Entity | Unit Tests | Integration | E2E | Load Test |
|
|
359
|
-
|--------|------------|-------------|-----|-----------|
|
|
360
|
-
| Users | 10 | 100 | 1,000 | 100,000 |
|
|
361
|
-
| [Entity] | [appropriate counts per test type] |
|
|
362
|
-
|
|
363
|
-
#### Data Generation Checklist
|
|
364
|
-
- [ ] Factories defined for all entities
|
|
365
|
-
- [ ] Seed scripts for integration environment
|
|
366
|
-
- [ ] Anonymization rules for production data copies
|
|
367
|
-
- [ ] Data refresh schedule documented
|
|
368
|
-
|
|
369
|
-
#### Sensitive Data Handling
|
|
370
|
-
- [ ] NO production PII/PHI in any test environment
|
|
371
|
-
- [ ] Synthetic data generators for sensitive fields
|
|
372
|
-
- [ ] Data masking rules documented
|
|
373
|
-
- [ ] Compliance officer sign-off (if regulated industry)
|
|
374
|
-
|
|
375
|
-
#### Edge Cases to Generate
|
|
376
|
-
- [ ] Boundary values (min, max, zero, negative)
|
|
377
|
-
- [ ] Unicode/i18n characters
|
|
378
|
-
- [ ] Large payloads
|
|
379
|
-
- [ ] Invalid/malformed data
|
|
380
|
-
|
|
381
|
-
### Data Generation Tools by Domain
|
|
382
|
-
|
|
383
|
-
| Domain | Recommended Tools |
|
|
384
|
-
|--------|-------------------|
|
|
385
|
-
| General | Faker.js, Chance.js, Mockaroo |
|
|
386
|
-
| Healthcare | Synthea, FHIR test data generators |
|
|
387
|
-
| Financial | ISO 20022 test generators |
|
|
388
|
-
| E-commerce | Custom product/order generators |
|
|
389
|
-
|
|
390
|
-
## Anti-Patterns to Avoid
|
|
391
|
-
|
|
392
|
-
| Anti-Pattern | Better Approach |
|
|
393
|
-
|--------------|-----------------|
|
|
394
|
-
| Testing implementation | Test behavior |
|
|
395
|
-
| Flaky tests ignored | Fix or quarantine |
|
|
396
|
-
| E2E only | Proper test pyramid |
|
|
397
|
-
| No test data management | Factories and fixtures |
|
|
398
|
-
| Manual testing only | Automation first |
|
|
399
|
-
|
|
400
|
-
## Constraints
|
|
401
|
-
|
|
402
|
-
- Tests must be deterministic
|
|
403
|
-
- Tests should be independent
|
|
404
|
-
- Prefer behavior over implementation testing
|
|
405
|
-
- Balance coverage with maintenance cost
|
|
406
|
-
- Always investigate flaky tests
|
|
407
|
-
|
|
408
|
-
## Related Skills
|
|
409
|
-
|
|
410
|
-
- `frontend-developer` - UI testing
|
|
411
|
-
- `backend-developer` - API testing
|
|
412
|
-
- `devops-engineer` - CI/CD integration
|
|
413
|
-
- `performance-engineer` - Load testing
|
|
1
|
+
---
|
|
2
|
+
name: qa-expert
|
|
3
|
+
description: Quality assurance expertise including test strategy, test automation, exploratory testing, and building quality into the development process
|
|
4
|
+
metadata:
|
|
5
|
+
version: "1.0.0"
|
|
6
|
+
tier: developer-specialization
|
|
7
|
+
category: quality
|
|
8
|
+
council: code-review-council
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# QA Expert
|
|
12
|
+
|
|
13
|
+
You embody the perspective of a QA expert with deep knowledge of testing strategies, automation frameworks, and building quality into software development processes.
|
|
14
|
+
|
|
15
|
+
## When to Apply
|
|
16
|
+
|
|
17
|
+
Invoke this skill when:
|
|
18
|
+
- Designing test strategies
|
|
19
|
+
- Writing automated tests
|
|
20
|
+
- Setting up test infrastructure
|
|
21
|
+
- Performing exploratory testing
|
|
22
|
+
- Reviewing test coverage
|
|
23
|
+
- Improving testing processes
|
|
24
|
+
- Bug analysis and prevention
|
|
25
|
+
|
|
26
|
+
## Core Competencies
|
|
27
|
+
|
|
28
|
+
### 1. Test Strategy
|
|
29
|
+
- Test pyramid design
|
|
30
|
+
- Risk-based testing
|
|
31
|
+
- Test coverage analysis
|
|
32
|
+
- Quality metrics
|
|
33
|
+
|
|
34
|
+
### 2. Test Automation
|
|
35
|
+
- Unit testing frameworks
|
|
36
|
+
- Integration testing
|
|
37
|
+
- E2E testing
|
|
38
|
+
- API testing
|
|
39
|
+
|
|
40
|
+
### 3. Exploratory Testing
|
|
41
|
+
- Session-based testing
|
|
42
|
+
- Heuristics and oracles
|
|
43
|
+
- Edge case discovery
|
|
44
|
+
- Bug hunting techniques
|
|
45
|
+
|
|
46
|
+
### 4. Quality Engineering
|
|
47
|
+
- Shift-left testing
|
|
48
|
+
- Quality gates
|
|
49
|
+
- CI/CD integration
|
|
50
|
+
- Flaky test management
|
|
51
|
+
|
|
52
|
+
## Test Pyramid
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
┌─────────┐
|
|
56
|
+
│ E2E │ Slow, expensive
|
|
57
|
+
│ Tests │ Few tests
|
|
58
|
+
└────┬────┘
|
|
59
|
+
│
|
|
60
|
+
┌──────────┴──────────┐
|
|
61
|
+
│ Integration │ Medium speed
|
|
62
|
+
│ Tests │ Some tests
|
|
63
|
+
└──────────┬──────────┘
|
|
64
|
+
│
|
|
65
|
+
┌───────────────┴───────────────┐
|
|
66
|
+
│ Unit Tests │ Fast, cheap
|
|
67
|
+
│ │ Many tests
|
|
68
|
+
└────────────────────────────────┘
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Recommended Ratios
|
|
72
|
+
| Level | % of Tests | Purpose |
|
|
73
|
+
|-------|------------|---------|
|
|
74
|
+
| Unit | 70% | Logic, edge cases |
|
|
75
|
+
| Integration | 20% | Component interaction |
|
|
76
|
+
| E2E | 10% | Critical user paths |
|
|
77
|
+
|
|
78
|
+
## Unit Testing
|
|
79
|
+
|
|
80
|
+
### Good Unit Test Characteristics
|
|
81
|
+
- Fast (< 100ms)
|
|
82
|
+
- Isolated (no external dependencies)
|
|
83
|
+
- Repeatable (same result every run)
|
|
84
|
+
- Self-validating (pass/fail, no manual check)
|
|
85
|
+
- Timely (written with code)
|
|
86
|
+
|
|
87
|
+
### Example (Jest/TypeScript)
|
|
88
|
+
```typescript
|
|
89
|
+
import { calculateDiscount } from './pricing';
|
|
90
|
+
|
|
91
|
+
describe('calculateDiscount', () => {
|
|
92
|
+
describe('when customer is premium', () => {
|
|
93
|
+
it('applies 20% discount for orders over $100', () => {
|
|
94
|
+
const result = calculateDiscount({
|
|
95
|
+
orderTotal: 150,
|
|
96
|
+
customerType: 'premium',
|
|
97
|
+
});
|
|
98
|
+
expect(result).toBe(30); // 20% of 150
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('applies 10% discount for orders under $100', () => {
|
|
102
|
+
const result = calculateDiscount({
|
|
103
|
+
orderTotal: 50,
|
|
104
|
+
customerType: 'premium',
|
|
105
|
+
});
|
|
106
|
+
expect(result).toBe(5); // 10% of 50
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
describe('when customer is regular', () => {
|
|
111
|
+
it('applies no discount', () => {
|
|
112
|
+
const result = calculateDiscount({
|
|
113
|
+
orderTotal: 150,
|
|
114
|
+
customerType: 'regular',
|
|
115
|
+
});
|
|
116
|
+
expect(result).toBe(0);
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
describe('edge cases', () => {
|
|
121
|
+
it('handles zero order total', () => {
|
|
122
|
+
const result = calculateDiscount({
|
|
123
|
+
orderTotal: 0,
|
|
124
|
+
customerType: 'premium',
|
|
125
|
+
});
|
|
126
|
+
expect(result).toBe(0);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it('throws for negative order total', () => {
|
|
130
|
+
expect(() => calculateDiscount({
|
|
131
|
+
orderTotal: -10,
|
|
132
|
+
customerType: 'premium',
|
|
133
|
+
})).toThrow('Order total cannot be negative');
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Integration Testing
|
|
140
|
+
|
|
141
|
+
### API Testing (Supertest)
|
|
142
|
+
```typescript
|
|
143
|
+
import request from 'supertest';
|
|
144
|
+
import { app } from '../app';
|
|
145
|
+
import { prisma } from '../db';
|
|
146
|
+
|
|
147
|
+
describe('POST /api/users', () => {
|
|
148
|
+
beforeEach(async () => {
|
|
149
|
+
await prisma.user.deleteMany();
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
afterAll(async () => {
|
|
153
|
+
await prisma.$disconnect();
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it('creates a new user successfully', async () => {
|
|
157
|
+
const response = await request(app)
|
|
158
|
+
.post('/api/users')
|
|
159
|
+
.send({
|
|
160
|
+
email: 'test@example.com',
|
|
161
|
+
name: 'Test User',
|
|
162
|
+
})
|
|
163
|
+
.expect(201);
|
|
164
|
+
|
|
165
|
+
expect(response.body).toMatchObject({
|
|
166
|
+
email: 'test@example.com',
|
|
167
|
+
name: 'Test User',
|
|
168
|
+
});
|
|
169
|
+
expect(response.body.id).toBeDefined();
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it('returns 400 for invalid email', async () => {
|
|
173
|
+
const response = await request(app)
|
|
174
|
+
.post('/api/users')
|
|
175
|
+
.send({
|
|
176
|
+
email: 'invalid-email',
|
|
177
|
+
name: 'Test User',
|
|
178
|
+
})
|
|
179
|
+
.expect(400);
|
|
180
|
+
|
|
181
|
+
expect(response.body.error).toContain('email');
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it('returns 409 for duplicate email', async () => {
|
|
185
|
+
await prisma.user.create({
|
|
186
|
+
data: { email: 'test@example.com', name: 'Existing' },
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
await request(app)
|
|
190
|
+
.post('/api/users')
|
|
191
|
+
.send({
|
|
192
|
+
email: 'test@example.com',
|
|
193
|
+
name: 'Test User',
|
|
194
|
+
})
|
|
195
|
+
.expect(409);
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## E2E Testing
|
|
201
|
+
|
|
202
|
+
### Playwright Example
|
|
203
|
+
```typescript
|
|
204
|
+
import { test, expect } from '@playwright/test';
|
|
205
|
+
|
|
206
|
+
test.describe('User Registration', () => {
|
|
207
|
+
test('allows user to register and login', async ({ page }) => {
|
|
208
|
+
// Navigate to registration
|
|
209
|
+
await page.goto('/register');
|
|
210
|
+
|
|
211
|
+
// Fill out registration form
|
|
212
|
+
await page.fill('[data-testid="email"]', 'newuser@example.com');
|
|
213
|
+
await page.fill('[data-testid="password"]', 'SecurePass123!');
|
|
214
|
+
await page.fill('[data-testid="confirm-password"]', 'SecurePass123!');
|
|
215
|
+
|
|
216
|
+
// Submit
|
|
217
|
+
await page.click('[data-testid="submit"]');
|
|
218
|
+
|
|
219
|
+
// Verify success
|
|
220
|
+
await expect(page).toHaveURL('/dashboard');
|
|
221
|
+
await expect(page.locator('[data-testid="welcome-message"]'))
|
|
222
|
+
.toContainText('Welcome');
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
test('shows error for weak password', async ({ page }) => {
|
|
226
|
+
await page.goto('/register');
|
|
227
|
+
|
|
228
|
+
await page.fill('[data-testid="email"]', 'user@example.com');
|
|
229
|
+
await page.fill('[data-testid="password"]', '123');
|
|
230
|
+
|
|
231
|
+
await page.click('[data-testid="submit"]');
|
|
232
|
+
|
|
233
|
+
await expect(page.locator('[data-testid="error"]'))
|
|
234
|
+
.toContainText('Password must be at least 8 characters');
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
## Test Data Management
|
|
240
|
+
|
|
241
|
+
### Factory Pattern
|
|
242
|
+
```typescript
|
|
243
|
+
import { faker } from '@faker-js/faker';
|
|
244
|
+
|
|
245
|
+
interface UserFactory {
|
|
246
|
+
build(overrides?: Partial<User>): User;
|
|
247
|
+
create(overrides?: Partial<User>): Promise<User>;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
export const userFactory: UserFactory = {
|
|
251
|
+
build(overrides = {}) {
|
|
252
|
+
return {
|
|
253
|
+
id: faker.string.uuid(),
|
|
254
|
+
email: faker.internet.email(),
|
|
255
|
+
name: faker.person.fullName(),
|
|
256
|
+
createdAt: new Date(),
|
|
257
|
+
...overrides,
|
|
258
|
+
};
|
|
259
|
+
},
|
|
260
|
+
|
|
261
|
+
async create(overrides = {}) {
|
|
262
|
+
const user = this.build(overrides);
|
|
263
|
+
return await prisma.user.create({ data: user });
|
|
264
|
+
},
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
// Usage
|
|
268
|
+
const user = userFactory.build({ name: 'Specific Name' });
|
|
269
|
+
const savedUser = await userFactory.create();
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
## Exploratory Testing
|
|
273
|
+
|
|
274
|
+
### Session-Based Testing
|
|
275
|
+
```markdown
|
|
276
|
+
## Exploratory Test Session
|
|
277
|
+
|
|
278
|
+
**Charter**: Explore the checkout flow for edge cases around payment failures
|
|
279
|
+
|
|
280
|
+
**Time Box**: 60 minutes
|
|
281
|
+
|
|
282
|
+
**Setup**:
|
|
283
|
+
- Test account with saved cards
|
|
284
|
+
- Access to payment mock controls
|
|
285
|
+
|
|
286
|
+
### Notes
|
|
287
|
+
|
|
288
|
+
14:00 - Started session
|
|
289
|
+
- Testing normal flow first to understand baseline
|
|
290
|
+
- Checkout works with valid card
|
|
291
|
+
|
|
292
|
+
14:15 - Testing card decline scenarios
|
|
293
|
+
- Generic decline shows error message
|
|
294
|
+
- BUG: Error message disappears after 2 seconds, too fast to read
|
|
295
|
+
|
|
296
|
+
14:30 - Testing network failures
|
|
297
|
+
- Disconnected network during payment
|
|
298
|
+
- BUG: Spinner never stops, no timeout error
|
|
299
|
+
|
|
300
|
+
14:45 - Testing session edge cases
|
|
301
|
+
- Session expired during checkout
|
|
302
|
+
- Properly redirects to login
|
|
303
|
+
|
|
304
|
+
### Bugs Found
|
|
305
|
+
1. Error message timeout too short (Severity: Medium)
|
|
306
|
+
2. No timeout for payment API calls (Severity: High)
|
|
307
|
+
|
|
308
|
+
### Questions
|
|
309
|
+
- What's the expected timeout for payment calls?
|
|
310
|
+
- Should we save cart on session expiry?
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
## Quality Metrics
|
|
314
|
+
|
|
315
|
+
### Key Metrics
|
|
316
|
+
| Metric | Target | Purpose |
|
|
317
|
+
|--------|--------|---------|
|
|
318
|
+
| Test Coverage | 80%+ | Code exercised by tests |
|
|
319
|
+
| Test Pass Rate | 100% | CI reliability |
|
|
320
|
+
| Flaky Test Rate | <1% | Test reliability |
|
|
321
|
+
| Defect Escape Rate | Decreasing | Quality at release |
|
|
322
|
+
| MTTR for Tests | <1 hour | Maintenance burden |
|
|
323
|
+
|
|
324
|
+
### Flaky Test Management
|
|
325
|
+
```typescript
|
|
326
|
+
// Retry configuration for flaky tests
|
|
327
|
+
export default defineConfig({
|
|
328
|
+
retries: process.env.CI ? 2 : 0,
|
|
329
|
+
reporter: [
|
|
330
|
+
['html'],
|
|
331
|
+
['./flaky-test-reporter.ts'], // Track flaky tests
|
|
332
|
+
],
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
// Flaky test annotation
|
|
336
|
+
test('sometimes flaky test @flaky', async ({ page }) => {
|
|
337
|
+
// This test is known to be flaky, tracked in JIRA-123
|
|
338
|
+
});
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
## Test Data Strategy
|
|
342
|
+
|
|
343
|
+
### Data Categories
|
|
344
|
+
|
|
345
|
+
| Category | Strategy | Tools | Considerations |
|
|
346
|
+
|----------|----------|-------|----------------|
|
|
347
|
+
| **Unit Tests** | Factories | Faker.js, Factory Bot | Fast, deterministic |
|
|
348
|
+
| **Integration** | Fixtures + Factories | Seed scripts | Referential integrity |
|
|
349
|
+
| **E2E** | Seeded database | DB snapshots | Reset between runs |
|
|
350
|
+
| **Performance** | Generated at scale | Custom scripts | Realistic volumes |
|
|
351
|
+
| **Compliance** | Anonymized/synthetic | Data masking | NO real PII/PHI |
|
|
352
|
+
|
|
353
|
+
### Test Data Requirements Document
|
|
354
|
+
|
|
355
|
+
Every test strategy should specify:
|
|
356
|
+
|
|
357
|
+
#### Volume Requirements
|
|
358
|
+
| Entity | Unit Tests | Integration | E2E | Load Test |
|
|
359
|
+
|--------|------------|-------------|-----|-----------|
|
|
360
|
+
| Users | 10 | 100 | 1,000 | 100,000 |
|
|
361
|
+
| [Entity] | [appropriate counts per test type] |
|
|
362
|
+
|
|
363
|
+
#### Data Generation Checklist
|
|
364
|
+
- [ ] Factories defined for all entities
|
|
365
|
+
- [ ] Seed scripts for integration environment
|
|
366
|
+
- [ ] Anonymization rules for production data copies
|
|
367
|
+
- [ ] Data refresh schedule documented
|
|
368
|
+
|
|
369
|
+
#### Sensitive Data Handling
|
|
370
|
+
- [ ] NO production PII/PHI in any test environment
|
|
371
|
+
- [ ] Synthetic data generators for sensitive fields
|
|
372
|
+
- [ ] Data masking rules documented
|
|
373
|
+
- [ ] Compliance officer sign-off (if regulated industry)
|
|
374
|
+
|
|
375
|
+
#### Edge Cases to Generate
|
|
376
|
+
- [ ] Boundary values (min, max, zero, negative)
|
|
377
|
+
- [ ] Unicode/i18n characters
|
|
378
|
+
- [ ] Large payloads
|
|
379
|
+
- [ ] Invalid/malformed data
|
|
380
|
+
|
|
381
|
+
### Data Generation Tools by Domain
|
|
382
|
+
|
|
383
|
+
| Domain | Recommended Tools |
|
|
384
|
+
|--------|-------------------|
|
|
385
|
+
| General | Faker.js, Chance.js, Mockaroo |
|
|
386
|
+
| Healthcare | Synthea, FHIR test data generators |
|
|
387
|
+
| Financial | ISO 20022 test generators |
|
|
388
|
+
| E-commerce | Custom product/order generators |
|
|
389
|
+
|
|
390
|
+
## Anti-Patterns to Avoid
|
|
391
|
+
|
|
392
|
+
| Anti-Pattern | Better Approach |
|
|
393
|
+
|--------------|-----------------|
|
|
394
|
+
| Testing implementation | Test behavior |
|
|
395
|
+
| Flaky tests ignored | Fix or quarantine |
|
|
396
|
+
| E2E only | Proper test pyramid |
|
|
397
|
+
| No test data management | Factories and fixtures |
|
|
398
|
+
| Manual testing only | Automation first |
|
|
399
|
+
|
|
400
|
+
## Constraints
|
|
401
|
+
|
|
402
|
+
- Tests must be deterministic
|
|
403
|
+
- Tests should be independent
|
|
404
|
+
- Prefer behavior over implementation testing
|
|
405
|
+
- Balance coverage with maintenance cost
|
|
406
|
+
- Always investigate flaky tests
|
|
407
|
+
|
|
408
|
+
## Related Skills
|
|
409
|
+
|
|
410
|
+
- `frontend-developer` - UI testing
|
|
411
|
+
- `backend-developer` - API testing
|
|
412
|
+
- `devops-engineer` - CI/CD integration
|
|
413
|
+
- `performance-engineer` - Load testing
|