opencode-agile-agent 1.0.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/README.md +71 -0
- package/bin/cli.js +434 -0
- package/bin/validate-templates.js +58 -0
- package/package.json +52 -0
- package/templates/.opencode/ARCHITECTURE.md +368 -0
- package/templates/.opencode/README.md +391 -0
- package/templates/.opencode/agents/api-designer.md +312 -0
- package/templates/.opencode/agents/backend-specialist.md +214 -0
- package/templates/.opencode/agents/code-archaeologist.md +260 -0
- package/templates/.opencode/agents/database-architect.md +212 -0
- package/templates/.opencode/agents/debugger.md +302 -0
- package/templates/.opencode/agents/developer.md +523 -0
- package/templates/.opencode/agents/devops-engineer.md +253 -0
- package/templates/.opencode/agents/documentation-writer.md +247 -0
- package/templates/.opencode/agents/explorer-agent.md +239 -0
- package/templates/.opencode/agents/feature-lead.md +302 -0
- package/templates/.opencode/agents/frontend-specialist.md +186 -0
- package/templates/.opencode/agents/game-developer.md +391 -0
- package/templates/.opencode/agents/mobile-developer.md +264 -0
- package/templates/.opencode/agents/orchestrator.md +463 -0
- package/templates/.opencode/agents/penetration-tester.md +256 -0
- package/templates/.opencode/agents/performance-optimizer.md +292 -0
- package/templates/.opencode/agents/pr-reviewer.md +468 -0
- package/templates/.opencode/agents/product-manager.md +225 -0
- package/templates/.opencode/agents/product-owner.md +264 -0
- package/templates/.opencode/agents/project-planner.md +248 -0
- package/templates/.opencode/agents/qa-automation-engineer.md +276 -0
- package/templates/.opencode/agents/security-auditor.md +260 -0
- package/templates/.opencode/agents/seo-specialist.md +266 -0
- package/templates/.opencode/agents/system-analyst.md +428 -0
- package/templates/.opencode/agents/test-engineer.md +229 -0
- package/templates/.opencode/config.template.json +129 -0
- package/templates/.opencode/rules/coding-standards.md +250 -0
- package/templates/.opencode/rules/git-conventions.md +149 -0
- package/templates/.opencode/skills/api-patterns/SKILL.md +162 -0
- package/templates/.opencode/skills/brainstorming/SKILL.md +255 -0
- package/templates/.opencode/skills/clean-code/SKILL.md +351 -0
- package/templates/.opencode/skills/code-philosophy/SKILL.md +512 -0
- package/templates/.opencode/skills/frontend-design/SKILL.md +237 -0
- package/templates/.opencode/skills/intelligent-routing/SKILL.md +195 -0
- package/templates/.opencode/skills/parallel-agents/SKILL.md +274 -0
- package/templates/.opencode/skills/plan-writing/SKILL.md +251 -0
- package/templates/.opencode/skills/systematic-debugging/SKILL.md +210 -0
- package/templates/.opencode/skills/testing-patterns/SKILL.md +252 -0
- package/templates/.opencode/workflows/brainstorm.md +110 -0
- package/templates/.opencode/workflows/create.md +108 -0
- package/templates/.opencode/workflows/debug.md +128 -0
- package/templates/.opencode/workflows/deploy.md +160 -0
- package/templates/.opencode/workflows/enhance.md +253 -0
- package/templates/.opencode/workflows/orchestrate.md +130 -0
- package/templates/.opencode/workflows/plan.md +163 -0
- package/templates/.opencode/workflows/review.md +135 -0
- package/templates/.opencode/workflows/status.md +102 -0
- package/templates/.opencode/workflows/test.md +146 -0
- package/templates/AGENTS.template.md +426 -0
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: plan-writing
|
|
3
|
+
description: Structured planning and task breakdown techniques.
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Plan Writing
|
|
8
|
+
|
|
9
|
+
Structured approaches to creating plans, breaking down tasks, and defining success criteria.
|
|
10
|
+
|
|
11
|
+
## Plan Structure
|
|
12
|
+
|
|
13
|
+
### Minimal Plan Template
|
|
14
|
+
|
|
15
|
+
```markdown
|
|
16
|
+
# PLAN: [Feature Name]
|
|
17
|
+
|
|
18
|
+
## What
|
|
19
|
+
Brief description of what we're building.
|
|
20
|
+
|
|
21
|
+
## Why
|
|
22
|
+
Business justification and user value.
|
|
23
|
+
|
|
24
|
+
## How
|
|
25
|
+
High-level technical approach.
|
|
26
|
+
|
|
27
|
+
## Tasks
|
|
28
|
+
- [ ] Task 1
|
|
29
|
+
- [ ] Task 2
|
|
30
|
+
- [ ] Task 3
|
|
31
|
+
|
|
32
|
+
## Success Criteria
|
|
33
|
+
- [ ] Criterion 1
|
|
34
|
+
- [ ] Criterion 2
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Comprehensive Plan Template
|
|
38
|
+
|
|
39
|
+
```markdown
|
|
40
|
+
# PLAN: [Feature Name]
|
|
41
|
+
|
|
42
|
+
## Executive Summary
|
|
43
|
+
One paragraph overview.
|
|
44
|
+
|
|
45
|
+
## Problem Statement
|
|
46
|
+
What problem are we solving?
|
|
47
|
+
|
|
48
|
+
## Proposed Solution
|
|
49
|
+
How will we solve it?
|
|
50
|
+
|
|
51
|
+
## User Stories
|
|
52
|
+
1. As a [user], I want [goal] so that [benefit]
|
|
53
|
+
2. ...
|
|
54
|
+
|
|
55
|
+
## Technical Design
|
|
56
|
+
### Architecture
|
|
57
|
+
[Diagram or description]
|
|
58
|
+
|
|
59
|
+
### API Design
|
|
60
|
+
[Endpoints/contracts]
|
|
61
|
+
|
|
62
|
+
### Data Model
|
|
63
|
+
[Schema/ERD]
|
|
64
|
+
|
|
65
|
+
## Implementation Plan
|
|
66
|
+
### Phase 1: Foundation
|
|
67
|
+
- [ ] Task 1.1
|
|
68
|
+
- [ ] Task 1.2
|
|
69
|
+
|
|
70
|
+
### Phase 2: Core Features
|
|
71
|
+
- [ ] Task 2.1
|
|
72
|
+
- [ ] Task 2.2
|
|
73
|
+
|
|
74
|
+
### Phase 3: Polish
|
|
75
|
+
- [ ] Task 3.1
|
|
76
|
+
- [ ] Task 3.2
|
|
77
|
+
|
|
78
|
+
## Dependencies
|
|
79
|
+
- Dependency 1
|
|
80
|
+
- Dependency 2
|
|
81
|
+
|
|
82
|
+
## Risks & Mitigations
|
|
83
|
+
| Risk | Likelihood | Impact | Mitigation |
|
|
84
|
+
|------|------------|--------|------------|
|
|
85
|
+
| ... | ... | ... | ... |
|
|
86
|
+
|
|
87
|
+
## Success Metrics
|
|
88
|
+
| Metric | Target | How Measured |
|
|
89
|
+
|--------|--------|--------------|
|
|
90
|
+
| ... | ... | ... |
|
|
91
|
+
|
|
92
|
+
## Timeline
|
|
93
|
+
- Phase 1: [dates]
|
|
94
|
+
- Phase 2: [dates]
|
|
95
|
+
- Phase 3: [dates]
|
|
96
|
+
|
|
97
|
+
## Open Questions
|
|
98
|
+
1. [Question] - Owner: [name]
|
|
99
|
+
2. [Question] - Owner: [name]
|
|
100
|
+
|
|
101
|
+
## Appendix
|
|
102
|
+
- [Supporting documents]
|
|
103
|
+
- [Research notes]
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Task Breakdown
|
|
107
|
+
|
|
108
|
+
### WBS (Work Breakdown Structure)
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
Feature: User Authentication
|
|
112
|
+
├── 1. Registration
|
|
113
|
+
│ ├── 1.1 Registration form UI
|
|
114
|
+
│ ├── 1.2 Form validation
|
|
115
|
+
│ ├── 1.3 API endpoint
|
|
116
|
+
│ ├── 1.4 Email verification
|
|
117
|
+
│ └── 1.5 Password hashing
|
|
118
|
+
├── 2. Login
|
|
119
|
+
│ ├── 2.1 Login form UI
|
|
120
|
+
│ ├── 2.2 JWT generation
|
|
121
|
+
│ ├── 2.3 Session management
|
|
122
|
+
│ └── 2.4 Logout flow
|
|
123
|
+
└── 3. Password Reset
|
|
124
|
+
├── 3.1 Forgot password form
|
|
125
|
+
├── 3.2 Reset token generation
|
|
126
|
+
└── 3.3 Reset password form
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Task Sizing
|
|
130
|
+
|
|
131
|
+
| Size | Duration | Characteristics |
|
|
132
|
+
|------|----------|-----------------|
|
|
133
|
+
| **XS** | < 1 hour | Typo fix, config change |
|
|
134
|
+
| **S** | 1-4 hours | Simple component, small fix |
|
|
135
|
+
| **M** | 4-8 hours | Feature with multiple parts |
|
|
136
|
+
| **L** | 1-2 days | Complex feature, multiple files |
|
|
137
|
+
| **XL** | 2-5 days | Major feature, needs breakdown |
|
|
138
|
+
|
|
139
|
+
### Dependency Mapping
|
|
140
|
+
|
|
141
|
+
```markdown
|
|
142
|
+
Task Dependencies:
|
|
143
|
+
|
|
144
|
+
A ─────► B ─────► D
|
|
145
|
+
│
|
|
146
|
+
└───────► C ─────► E
|
|
147
|
+
|
|
148
|
+
Execution Order:
|
|
149
|
+
1. A (no dependencies)
|
|
150
|
+
2. B (depends on A)
|
|
151
|
+
3. C (depends on B)
|
|
152
|
+
4. D (depends on B)
|
|
153
|
+
5. E (depends on C)
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Success Criteria
|
|
157
|
+
|
|
158
|
+
### SMART Criteria
|
|
159
|
+
|
|
160
|
+
| Letter | Meaning | Example |
|
|
161
|
+
|--------|---------|---------|
|
|
162
|
+
| **S**pecific | Clear and precise | "Reduce load time" → "Reduce LCP to < 2.5s" |
|
|
163
|
+
| **M**easurable | Quantifiable | "Improve UX" → "Increase conversion by 10%" |
|
|
164
|
+
| **A**chievable | Realistic | Based on resources and constraints |
|
|
165
|
+
| **R**elevant | Aligned with goals | Supports business objectives |
|
|
166
|
+
| **T**ime-bound | Has deadline | "Complete by Q2" |
|
|
167
|
+
|
|
168
|
+
### Acceptance Criteria Template
|
|
169
|
+
|
|
170
|
+
```markdown
|
|
171
|
+
## User Story
|
|
172
|
+
As a [user type], I want [goal] so that [benefit]
|
|
173
|
+
|
|
174
|
+
## Acceptance Criteria
|
|
175
|
+
- [ ] Given [context], when [action], then [outcome]
|
|
176
|
+
- [ ] Given [context], when [action], then [outcome]
|
|
177
|
+
- [ ] Given [context], when [action], then [outcome]
|
|
178
|
+
|
|
179
|
+
## Edge Cases
|
|
180
|
+
- [ ] Handle [edge case]
|
|
181
|
+
- [ ] Handle [edge case]
|
|
182
|
+
|
|
183
|
+
## Non-Functional
|
|
184
|
+
- [ ] Performance: [requirement]
|
|
185
|
+
- [ ] Security: [requirement]
|
|
186
|
+
- [ ] Accessibility: [requirement]
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Risk Assessment
|
|
190
|
+
|
|
191
|
+
### Risk Matrix
|
|
192
|
+
|
|
193
|
+
```
|
|
194
|
+
IMPACT
|
|
195
|
+
Low Med High
|
|
196
|
+
┌──────┬──────┬──────┐
|
|
197
|
+
High │Monitor│Plan │Act │
|
|
198
|
+
LIK ├──────┼──────┼──────┤
|
|
199
|
+
Med │Accept │Monitor│Plan │
|
|
200
|
+
├──────┼──────┼──────┤
|
|
201
|
+
Low │Accept │Accept │Monitor│
|
|
202
|
+
└──────┴──────┴──────┘
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### Risk Register Template
|
|
206
|
+
|
|
207
|
+
```markdown
|
|
208
|
+
| ID | Risk | Likelihood | Impact | Score | Mitigation | Owner |
|
|
209
|
+
|----|------|------------|--------|-------|------------|-------|
|
|
210
|
+
| R1 | API changes | Medium | High | 6 | Version lock | Dev |
|
|
211
|
+
| R2 | Staff change | Low | High | 3 | Documentation | PM |
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## Estimation Techniques
|
|
215
|
+
|
|
216
|
+
### Planning Poker
|
|
217
|
+
|
|
218
|
+
```
|
|
219
|
+
Team members estimate:
|
|
220
|
+
- Developer A: 5
|
|
221
|
+
- Developer B: 8
|
|
222
|
+
- Developer C: 5
|
|
223
|
+
- Developer D: 13
|
|
224
|
+
|
|
225
|
+
Discuss high/low outliers, reach consensus.
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### Three-Point Estimation
|
|
229
|
+
|
|
230
|
+
```
|
|
231
|
+
Optimistic (O): 2 days
|
|
232
|
+
Most Likely (M): 4 days
|
|
233
|
+
Pessimistic (P): 8 days
|
|
234
|
+
|
|
235
|
+
Expected = (O + 4M + P) / 6 = (2 + 16 + 8) / 6 = 4.33 days
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
## Plan Review Checklist
|
|
239
|
+
|
|
240
|
+
- [ ] **Clear Objective**: What and why are clear
|
|
241
|
+
- [ ] **Complete Breakdown**: All tasks identified
|
|
242
|
+
- [ ] **Dependencies Mapped**: Order is logical
|
|
243
|
+
- [ ] **Sized Appropriately**: Tasks are achievable
|
|
244
|
+
- [ ] **Success Criteria**: Measurable outcomes defined
|
|
245
|
+
- [ ] **Risks Identified**: Major risks documented
|
|
246
|
+
- [ ] **Timeline Realistic**: Based on estimates
|
|
247
|
+
- [ ] **Stakeholders Aligned**: Key people approve
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
**A good plan eliminates ambiguity and enables execution.**
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: systematic-debugging
|
|
3
|
+
description: Methodical approach to identifying and fixing bugs.
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Systematic Debugging
|
|
8
|
+
|
|
9
|
+
A methodical approach to finding and fixing bugs efficiently.
|
|
10
|
+
|
|
11
|
+
## Debugging Methodology
|
|
12
|
+
|
|
13
|
+
### The Scientific Method
|
|
14
|
+
|
|
15
|
+
1. **Observe** - What's the symptom?
|
|
16
|
+
2. **Hypothesize** - What could cause this?
|
|
17
|
+
3. **Test** - Verify or disprove hypothesis
|
|
18
|
+
4. **Repeat** - Until root cause found
|
|
19
|
+
5. **Fix** - Address the root cause
|
|
20
|
+
6. **Verify** - Confirm fix works
|
|
21
|
+
7. **Document** - Record for future
|
|
22
|
+
|
|
23
|
+
## Step-by-Step Process
|
|
24
|
+
|
|
25
|
+
### Step 1: Reproduce
|
|
26
|
+
|
|
27
|
+
```markdown
|
|
28
|
+
Document exact steps:
|
|
29
|
+
1. Open browser
|
|
30
|
+
2. Navigate to /dashboard
|
|
31
|
+
3. Click "Export" button
|
|
32
|
+
4. Error appears
|
|
33
|
+
|
|
34
|
+
Environment:
|
|
35
|
+
- Browser: Chrome 120
|
|
36
|
+
- OS: macOS 14
|
|
37
|
+
- Node: v20.10.0
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Step 2: Gather Information
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# Check logs
|
|
44
|
+
tail -f /var/log/app.log
|
|
45
|
+
|
|
46
|
+
# Check recent changes
|
|
47
|
+
git log --oneline -10
|
|
48
|
+
|
|
49
|
+
# Check error stack trace
|
|
50
|
+
Error: Cannot read property 'map' of undefined
|
|
51
|
+
at exportData (src/utils/export.ts:45)
|
|
52
|
+
at handleClick (src/components/ExportButton.tsx:23)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Step 3: Hypothesize
|
|
56
|
+
|
|
57
|
+
```markdown
|
|
58
|
+
Possible causes (ranked by likelihood):
|
|
59
|
+
1. data is null/undefined when exportData is called
|
|
60
|
+
2. data structure changed but exportData not updated
|
|
61
|
+
3. Race condition in data loading
|
|
62
|
+
4. API returning unexpected format
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Step 4: Test Hypotheses
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
// Add defensive logging
|
|
69
|
+
console.log('exportData called with:', { data, type: typeof data });
|
|
70
|
+
|
|
71
|
+
// Add type guard
|
|
72
|
+
if (!data || !Array.isArray(data)) {
|
|
73
|
+
console.error('Invalid data for export:', data);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Step 5: Fix Root Cause
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
// ❌ Fix symptom only
|
|
82
|
+
const items = data?.items || []; // Hides the real problem
|
|
83
|
+
|
|
84
|
+
// ✅ Fix root cause
|
|
85
|
+
// Investigate WHY data is undefined and fix upstream
|
|
86
|
+
async function loadData() {
|
|
87
|
+
const response = await fetch('/api/data');
|
|
88
|
+
if (!response.ok) {
|
|
89
|
+
throw new Error(`Failed to load data: ${response.status}`);
|
|
90
|
+
}
|
|
91
|
+
return response.json();
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Common Bug Patterns
|
|
96
|
+
|
|
97
|
+
### Null/Undefined Errors
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
// ❌ Crashes on null
|
|
101
|
+
const name = user.profile.name;
|
|
102
|
+
|
|
103
|
+
// ✅ Safe access
|
|
104
|
+
const name = user?.profile?.name ?? 'Unknown';
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Race Conditions
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
// ❌ Race condition
|
|
111
|
+
let data;
|
|
112
|
+
fetchData().then(result => { data = result; });
|
|
113
|
+
console.log(data); // undefined!
|
|
114
|
+
|
|
115
|
+
// ✅ Proper async handling
|
|
116
|
+
const data = await fetchData();
|
|
117
|
+
console.log(data);
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### State Sync Issues
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
// ❌ Stale closure
|
|
124
|
+
const [count, setCount] = useState(0);
|
|
125
|
+
useEffect(() => {
|
|
126
|
+
const interval = setInterval(() => {
|
|
127
|
+
console.log(count); // Always 0!
|
|
128
|
+
}, 1000);
|
|
129
|
+
return () => clearInterval(interval);
|
|
130
|
+
}, []);
|
|
131
|
+
|
|
132
|
+
// ✅ Use ref or dependency
|
|
133
|
+
const countRef = useRef(count);
|
|
134
|
+
countRef.current = count;
|
|
135
|
+
// Or add count to dependencies
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Debugging Tools
|
|
139
|
+
|
|
140
|
+
### Console Debugging
|
|
141
|
+
|
|
142
|
+
```typescript
|
|
143
|
+
// Strategic logging
|
|
144
|
+
console.log('1. Before fetch');
|
|
145
|
+
const data = await fetch(url);
|
|
146
|
+
console.log('2. After fetch:', data);
|
|
147
|
+
const processed = processData(data);
|
|
148
|
+
console.log('3. After process:', processed);
|
|
149
|
+
|
|
150
|
+
// Performance timing
|
|
151
|
+
console.time('operation');
|
|
152
|
+
doSomething();
|
|
153
|
+
console.timeEnd('operation');
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Browser DevTools
|
|
157
|
+
|
|
158
|
+
```
|
|
159
|
+
1. Sources panel - Set breakpoints
|
|
160
|
+
2. Network panel - Check API calls
|
|
161
|
+
3. Console - Run expressions
|
|
162
|
+
4. React DevTools - Component tree
|
|
163
|
+
5. Performance - Record profile
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Node.js Debugging
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
# Inspector mode
|
|
170
|
+
node --inspect app.js
|
|
171
|
+
|
|
172
|
+
# Then open chrome://inspect
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## Debugging Checklist
|
|
176
|
+
|
|
177
|
+
- [ ] **Reproduced**: Can consistently reproduce
|
|
178
|
+
- [ ] **Isolated**: Narrowed to specific area
|
|
179
|
+
- [ ] **Root cause**: Understand WHY
|
|
180
|
+
- [ ] **Fix implemented**: Addresses cause, not symptom
|
|
181
|
+
- [ ] **Verified**: Fix resolves the issue
|
|
182
|
+
- [ ] **No regressions**: Other functionality intact
|
|
183
|
+
- [ ] **Tests added**: Prevents future occurrences
|
|
184
|
+
|
|
185
|
+
## Anti-Patterns to Avoid
|
|
186
|
+
|
|
187
|
+
### Shotgun Debugging
|
|
188
|
+
|
|
189
|
+
```
|
|
190
|
+
❌ Change random things hoping it works
|
|
191
|
+
✅ Change one thing at a time, verify each
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Console.log Everything
|
|
195
|
+
|
|
196
|
+
```
|
|
197
|
+
❌ console.log everywhere
|
|
198
|
+
✅ Strategic, minimal logging with context
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Fix Symptom, Not Cause
|
|
202
|
+
|
|
203
|
+
```
|
|
204
|
+
❌ Add null check to hide error
|
|
205
|
+
✅ Find why null occurs and fix upstream
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
**Systematic debugging finds root causes faster.**
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: testing-patterns
|
|
3
|
+
description: Testing strategies, patterns, and best practices for unit, integration, and E2E tests.
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Testing Patterns
|
|
8
|
+
|
|
9
|
+
Comprehensive testing strategies and best practices.
|
|
10
|
+
|
|
11
|
+
## Testing Pyramid
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
/\
|
|
15
|
+
/E2E\ Few, slow, critical paths
|
|
16
|
+
/------\
|
|
17
|
+
/ API \ Some, integration tests
|
|
18
|
+
/----------\
|
|
19
|
+
/ Unit \ Many, fast, isolated
|
|
20
|
+
/--------------\
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Unit Testing
|
|
24
|
+
|
|
25
|
+
### AAA Pattern
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
describe('calculateTotal', () => {
|
|
29
|
+
it('should sum item prices', () => {
|
|
30
|
+
// Arrange
|
|
31
|
+
const items = [{ price: 10 }, { price: 20 }];
|
|
32
|
+
|
|
33
|
+
// Act
|
|
34
|
+
const result = calculateTotal(items);
|
|
35
|
+
|
|
36
|
+
// Assert
|
|
37
|
+
expect(result).toBe(30);
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Test Edge Cases
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
describe('calculateTotal', () => {
|
|
46
|
+
it('should handle empty array', () => {
|
|
47
|
+
expect(calculateTotal([])).toBe(0);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('should handle null', () => {
|
|
51
|
+
expect(calculateTotal(null)).toBe(0);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('should handle negative prices', () => {
|
|
55
|
+
expect(calculateTotal([{ price: -5 }])).toBe(-5);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Mocking
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
// Mock external dependency
|
|
64
|
+
jest.mock('./api');
|
|
65
|
+
api.fetchUser.mockResolvedValue({ id: 1, name: 'Test' });
|
|
66
|
+
|
|
67
|
+
// Mock function
|
|
68
|
+
const mockCallback = jest.fn();
|
|
69
|
+
mockCallback.mockReturnValue(true);
|
|
70
|
+
mockCallback.mockImplementation(x => x * 2);
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Integration Testing
|
|
74
|
+
|
|
75
|
+
### API Testing
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
describe('POST /api/users', () => {
|
|
79
|
+
it('should create user with valid data', async () => {
|
|
80
|
+
const response = await request(app)
|
|
81
|
+
.post('/api/users')
|
|
82
|
+
.send({ name: 'Test', email: 'test@example.com' });
|
|
83
|
+
|
|
84
|
+
expect(response.status).toBe(201);
|
|
85
|
+
expect(response.body.data.name).toBe('Test');
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('should reject invalid email', async () => {
|
|
89
|
+
const response = await request(app)
|
|
90
|
+
.post('/api/users')
|
|
91
|
+
.send({ name: 'Test', email: 'invalid' });
|
|
92
|
+
|
|
93
|
+
expect(response.status).toBe(400);
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Database Testing
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
describe('UserService', () => {
|
|
102
|
+
beforeAll(async () => {
|
|
103
|
+
await setupTestDatabase();
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
afterAll(async () => {
|
|
107
|
+
await teardownTestDatabase();
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
beforeEach(async () => {
|
|
111
|
+
await clearDatabase();
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('should create user', async () => {
|
|
115
|
+
const user = await UserService.create({ name: 'Test' });
|
|
116
|
+
expect(user.id).toBeDefined();
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## E2E Testing
|
|
122
|
+
|
|
123
|
+
### Page Object Model
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
// pages/LoginPage.ts
|
|
127
|
+
export class LoginPage {
|
|
128
|
+
constructor(private page: Page) {}
|
|
129
|
+
|
|
130
|
+
async goto() {
|
|
131
|
+
await this.page.goto('/login');
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
async login(email: string, password: string) {
|
|
135
|
+
await this.page.fill('[data-testid="email"]', email);
|
|
136
|
+
await this.page.fill('[data-testid="password"]', password);
|
|
137
|
+
await this.page.click('[data-testid="login-btn"]');
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// tests/auth.spec.ts
|
|
142
|
+
test('should login successfully', async ({ page }) => {
|
|
143
|
+
const loginPage = new LoginPage(page);
|
|
144
|
+
await loginPage.goto();
|
|
145
|
+
await loginPage.login('user@example.com', 'password');
|
|
146
|
+
|
|
147
|
+
await expect(page).toHaveURL('/dashboard');
|
|
148
|
+
});
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Test Selectors
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
// ❌ Brittle
|
|
155
|
+
await page.locator('.card > .title').click();
|
|
156
|
+
|
|
157
|
+
// ✅ Resilient
|
|
158
|
+
await page.locator('[data-testid="product-title"]').click();
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Test Organization
|
|
162
|
+
|
|
163
|
+
```
|
|
164
|
+
tests/
|
|
165
|
+
├── unit/
|
|
166
|
+
│ ├── utils/
|
|
167
|
+
│ │ └── calculate.test.ts
|
|
168
|
+
│ └── components/
|
|
169
|
+
│ └── Button.test.tsx
|
|
170
|
+
├── integration/
|
|
171
|
+
│ ├── api/
|
|
172
|
+
│ │ └── users.test.ts
|
|
173
|
+
│ └── services/
|
|
174
|
+
│ └── auth.test.ts
|
|
175
|
+
└── e2e/
|
|
176
|
+
├── auth.spec.ts
|
|
177
|
+
└── checkout.spec.ts
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## Coverage Guidelines
|
|
181
|
+
|
|
182
|
+
| Type | Target |
|
|
183
|
+
|------|--------|
|
|
184
|
+
| Statements | 80% |
|
|
185
|
+
| Branches | 75% |
|
|
186
|
+
| Functions | 85% |
|
|
187
|
+
| Lines | 80% |
|
|
188
|
+
|
|
189
|
+
## Best Practices
|
|
190
|
+
|
|
191
|
+
### Descriptive Names
|
|
192
|
+
|
|
193
|
+
```typescript
|
|
194
|
+
// ❌ Vague
|
|
195
|
+
test('user', () => {});
|
|
196
|
+
|
|
197
|
+
// ✅ Descriptive
|
|
198
|
+
test('should create user with valid email', () => {});
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### One Concept Per Test
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
// ❌ Multiple concepts
|
|
205
|
+
test('user operations', () => {
|
|
206
|
+
// Test create
|
|
207
|
+
// Test update
|
|
208
|
+
// Test delete
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
// ✅ One concept
|
|
212
|
+
test('should create user', () => {});
|
|
213
|
+
test('should update user', () => {});
|
|
214
|
+
test('should delete user', () => {});
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Test Behavior, Not Implementation
|
|
218
|
+
|
|
219
|
+
```typescript
|
|
220
|
+
// ❌ Tests implementation
|
|
221
|
+
expect(component.state.count).toBe(1);
|
|
222
|
+
|
|
223
|
+
// ✅ Tests behavior
|
|
224
|
+
expect(screen.getByText('Count: 1')).toBeInTheDocument();
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
## Anti-Patterns
|
|
228
|
+
|
|
229
|
+
### Testing Implementation
|
|
230
|
+
|
|
231
|
+
```
|
|
232
|
+
❌ Test that function calls internal helper
|
|
233
|
+
✅ Test the output/behavior
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### Shared State
|
|
237
|
+
|
|
238
|
+
```
|
|
239
|
+
❌ Tests that depend on each other
|
|
240
|
+
✅ Each test is independent
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### Overspecifying
|
|
244
|
+
|
|
245
|
+
```
|
|
246
|
+
❌ Assert every property
|
|
247
|
+
✅ Assert essential behavior
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
**Good tests enable confident refactoring.**
|