@su-record/vibe 2.4.56 โ 2.4.57
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.md +7 -18
- package/agents/compounder.md +1 -1
- package/agents/implementer.md +2 -1
- package/agents/simplifier.md +2 -1
- package/commands/vibe.run.md +4 -1
- package/commands/vibe.spec.md +56 -3
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +0 -4
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/postinstall.js +32 -1
- package/dist/cli/postinstall.js.map +1 -1
- package/dist/cli/setup.d.ts +18 -4
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +87 -27
- package/dist/cli/setup.js.map +1 -1
- package/dist/cli/types.d.ts +6 -0
- package/dist/cli/types.d.ts.map +1 -1
- package/languages/csharp-unity.md +516 -0
- package/languages/gdscript-godot.md +470 -0
- package/languages/ruby-rails.md +489 -0
- package/languages/typescript-angular.md +433 -0
- package/languages/typescript-astro.md +416 -0
- package/languages/typescript-electron.md +407 -0
- package/languages/typescript-nestjs.md +524 -0
- package/languages/typescript-svelte.md +407 -0
- package/languages/typescript-tauri.md +366 -0
- package/package.json +1 -1
- package/skills/vibe-capabilities.md +1 -1
- package/vibe/constitution.md +130 -97
- package/vibe/rules/core/communication-guide.md +50 -56
- package/vibe/rules/core/development-philosophy.md +35 -36
- package/vibe/rules/core/quick-start.md +66 -85
- package/vibe/rules/quality/bdd-contract-testing.md +94 -89
- package/vibe/rules/quality/checklist.md +132 -132
- package/vibe/rules/quality/testing-strategy.md +132 -129
- package/vibe/rules/standards/anti-patterns.md +74 -74
- package/vibe/rules/standards/code-structure.md +44 -44
- package/vibe/rules/standards/complexity-metrics.md +63 -62
- package/vibe/rules/standards/naming-conventions.md +72 -72
- package/vibe/templates/constitution-template.md +153 -95
- package/vibe/templates/contract-backend-template.md +41 -32
- package/vibe/templates/contract-frontend-template.md +35 -30
- package/vibe/templates/feature-template.md +33 -33
- package/vibe/templates/spec-template.md +118 -96
|
@@ -1,54 +1,54 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Testing Strategy for the AI Era
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## Core Principles
|
|
4
4
|
|
|
5
5
|
```markdown
|
|
6
|
-
โ
|
|
7
|
-
โ
|
|
8
|
-
โ
|
|
9
|
-
โ
|
|
10
|
-
โ
|
|
6
|
+
โ
Single Responsibility (SRP)
|
|
7
|
+
โ
Don't Repeat Yourself (DRY)
|
|
8
|
+
โ
Reusability
|
|
9
|
+
โ
Low Complexity
|
|
10
|
+
โ
Contract-First Design
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
##
|
|
13
|
+
## Test Priorities in AI-Driven Development
|
|
14
14
|
|
|
15
|
-
### 1. Contract Testing (
|
|
15
|
+
### 1. Contract Testing (Highest Priority) โญโญโญ
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
**Concept**: **Define contracts with types/schemas** before writing code
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
**Reason**: Since AI implements following contracts, type safety is automatically guaranteed
|
|
20
20
|
|
|
21
21
|
#### Python (Pydantic)
|
|
22
22
|
|
|
23
23
|
```python
|
|
24
|
-
#
|
|
24
|
+
# Contract definition (AI implements following this)
|
|
25
25
|
from pydantic import BaseModel, Field, EmailStr
|
|
26
26
|
|
|
27
27
|
class CreateUserRequest(BaseModel):
|
|
28
|
-
"""
|
|
28
|
+
"""User creation contract"""
|
|
29
29
|
email: EmailStr
|
|
30
30
|
username: str = Field(min_length=3, max_length=50)
|
|
31
31
|
password: str = Field(min_length=8)
|
|
32
32
|
age: int = Field(ge=0, le=150)
|
|
33
33
|
|
|
34
34
|
class UserResponse(BaseModel):
|
|
35
|
-
"""
|
|
35
|
+
"""User response contract"""
|
|
36
36
|
id: str
|
|
37
37
|
email: str
|
|
38
38
|
username: str
|
|
39
39
|
created_at: str
|
|
40
40
|
|
|
41
|
-
# AI
|
|
41
|
+
# AI cannot violate this contract (auto-validated)
|
|
42
42
|
```
|
|
43
43
|
|
|
44
44
|
#### TypeScript
|
|
45
45
|
|
|
46
46
|
```typescript
|
|
47
|
-
//
|
|
47
|
+
// Contract definition
|
|
48
48
|
interface CreateUserRequest {
|
|
49
49
|
email: string;
|
|
50
|
-
username: string; // 3-50
|
|
51
|
-
password: string; //
|
|
50
|
+
username: string; // 3-50 chars
|
|
51
|
+
password: string; // min 8 chars
|
|
52
52
|
age: number; // 0-150
|
|
53
53
|
}
|
|
54
54
|
|
|
@@ -59,7 +59,7 @@ interface UserResponse {
|
|
|
59
59
|
createdAt: string;
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
//
|
|
62
|
+
// Runtime validation with Zod
|
|
63
63
|
import { z } from 'zod';
|
|
64
64
|
|
|
65
65
|
const createUserSchema = z.object({
|
|
@@ -73,7 +73,7 @@ const createUserSchema = z.object({
|
|
|
73
73
|
#### Dart (Flutter)
|
|
74
74
|
|
|
75
75
|
```dart
|
|
76
|
-
//
|
|
76
|
+
// Contract definition
|
|
77
77
|
class CreateUserRequest {
|
|
78
78
|
const CreateUserRequest({
|
|
79
79
|
required this.email,
|
|
@@ -83,11 +83,11 @@ class CreateUserRequest {
|
|
|
83
83
|
});
|
|
84
84
|
|
|
85
85
|
final String email;
|
|
86
|
-
final String username; // 3-50
|
|
87
|
-
final String password; //
|
|
86
|
+
final String username; // 3-50 chars
|
|
87
|
+
final String password; // min 8 chars
|
|
88
88
|
final int age; // 0-150
|
|
89
89
|
|
|
90
|
-
// JSON
|
|
90
|
+
// JSON serialization (contract enforcement)
|
|
91
91
|
Map<String, dynamic> toJson() => {
|
|
92
92
|
'email': email,
|
|
93
93
|
'username': username,
|
|
@@ -97,24 +97,24 @@ class CreateUserRequest {
|
|
|
97
97
|
}
|
|
98
98
|
```
|
|
99
99
|
|
|
100
|
-
### 2. Integration Testing (
|
|
100
|
+
### 2. Integration Testing (High) โญโญโญ
|
|
101
101
|
|
|
102
|
-
|
|
102
|
+
**Concept**: **Test real scenarios** where multiple modules work together
|
|
103
103
|
|
|
104
|
-
|
|
104
|
+
**Reason**: Discovers module interaction errors that AI may have missed
|
|
105
105
|
|
|
106
106
|
```python
|
|
107
|
-
# โ
|
|
107
|
+
# โ
Integration test: Real business flow
|
|
108
108
|
@pytest.mark.asyncio
|
|
109
109
|
async def test_user_registration_flow():
|
|
110
110
|
"""
|
|
111
|
-
|
|
112
|
-
1.
|
|
113
|
-
2.
|
|
114
|
-
3.
|
|
115
|
-
4.
|
|
111
|
+
Scenario: New user registration
|
|
112
|
+
1. Check email duplication
|
|
113
|
+
2. Create user
|
|
114
|
+
3. Send welcome email
|
|
115
|
+
4. Create default settings
|
|
116
116
|
"""
|
|
117
|
-
# Given:
|
|
117
|
+
# Given: New user information
|
|
118
118
|
request = CreateUserRequest(
|
|
119
119
|
email="new@example.com",
|
|
120
120
|
username="newuser",
|
|
@@ -122,50 +122,50 @@ async def test_user_registration_flow():
|
|
|
122
122
|
age=25,
|
|
123
123
|
)
|
|
124
124
|
|
|
125
|
-
# When:
|
|
125
|
+
# When: Call registration API
|
|
126
126
|
response = await client.post("/api/users", json=request.dict())
|
|
127
127
|
|
|
128
|
-
# Then:
|
|
128
|
+
# Then: User creation succeeds
|
|
129
129
|
assert response.status_code == 201
|
|
130
130
|
data = response.json()
|
|
131
131
|
assert data["email"] == "new@example.com"
|
|
132
132
|
|
|
133
|
-
# And:
|
|
133
|
+
# And: Welcome email sent
|
|
134
134
|
assert email_service.sent_count == 1
|
|
135
135
|
|
|
136
|
-
# And:
|
|
136
|
+
# And: Default settings created
|
|
137
137
|
settings = await get_user_settings(data["id"])
|
|
138
138
|
assert settings is not None
|
|
139
139
|
```
|
|
140
140
|
|
|
141
141
|
```typescript
|
|
142
|
-
// โ
|
|
142
|
+
// โ
Integration test: React component + API
|
|
143
143
|
import { render, screen, waitFor } from '@testing-library/react';
|
|
144
144
|
import userEvent from '@testing-library/user-event';
|
|
145
145
|
import { UserRegistration } from './UserRegistration';
|
|
146
146
|
|
|
147
147
|
test('user can register successfully', async () => {
|
|
148
|
-
// Given:
|
|
148
|
+
// Given: Render registration form
|
|
149
149
|
render(<UserRegistration />);
|
|
150
150
|
|
|
151
|
-
// When:
|
|
151
|
+
// When: User fills form
|
|
152
152
|
await userEvent.type(screen.getByLabelText('Email'), 'new@example.com');
|
|
153
153
|
await userEvent.type(screen.getByLabelText('Username'), 'newuser');
|
|
154
154
|
await userEvent.type(screen.getByLabelText('Password'), 'password123');
|
|
155
155
|
await userEvent.click(screen.getByRole('button', { name: 'Sign Up' }));
|
|
156
156
|
|
|
157
|
-
// Then:
|
|
157
|
+
// Then: Success message displayed
|
|
158
158
|
await waitFor(() => {
|
|
159
159
|
expect(screen.getByText('Welcome!')).toBeInTheDocument();
|
|
160
160
|
});
|
|
161
161
|
});
|
|
162
162
|
```
|
|
163
163
|
|
|
164
|
-
### 3. Property-Based Testing (
|
|
164
|
+
### 3. Property-Based Testing (Medium) โญโญ
|
|
165
165
|
|
|
166
|
-
|
|
166
|
+
**Concept**: **Automatically generate inputs** across entire input range to test
|
|
167
167
|
|
|
168
|
-
|
|
168
|
+
**Reason**: Automatically discovers edge cases AI didn't think of
|
|
169
169
|
|
|
170
170
|
```python
|
|
171
171
|
# โ
Property-based testing (Hypothesis)
|
|
@@ -177,7 +177,7 @@ from hypothesis import given, strategies as st
|
|
|
177
177
|
username=st.text(min_size=3, max_size=50),
|
|
178
178
|
)
|
|
179
179
|
def test_user_creation_with_any_valid_input(age, email, username):
|
|
180
|
-
"""
|
|
180
|
+
"""User creation possible with any valid input"""
|
|
181
181
|
user = create_user(email=email, username=username, age=age)
|
|
182
182
|
assert user.age == age
|
|
183
183
|
assert user.email == email
|
|
@@ -190,8 +190,8 @@ import fc from 'fast-check';
|
|
|
190
190
|
test('discount calculation always returns valid percentage', () => {
|
|
191
191
|
fc.assert(
|
|
192
192
|
fc.property(
|
|
193
|
-
fc.float({ min: 0, max: 10000 }), //
|
|
194
|
-
fc.float({ min: 0, max: 1 }), //
|
|
193
|
+
fc.float({ min: 0, max: 10000 }), // price
|
|
194
|
+
fc.float({ min: 0, max: 1 }), // discount rate
|
|
195
195
|
(price, rate) => {
|
|
196
196
|
const discount = calculateDiscount(price, rate);
|
|
197
197
|
return discount >= 0 && discount <= price;
|
|
@@ -201,22 +201,22 @@ test('discount calculation always returns valid percentage', () => {
|
|
|
201
201
|
});
|
|
202
202
|
```
|
|
203
203
|
|
|
204
|
-
### 4. Unit Testing (
|
|
204
|
+
### 4. Unit Testing (Low, Selective) โญ
|
|
205
205
|
|
|
206
|
-
|
|
206
|
+
**Concept**: Test individual functions/methods
|
|
207
207
|
|
|
208
|
-
|
|
208
|
+
**When to write**: **Only for complex business logic** selectively
|
|
209
209
|
|
|
210
210
|
```python
|
|
211
|
-
# โ
Unit Test:
|
|
211
|
+
# โ
Unit Test: Complex business rules
|
|
212
212
|
def test_tier_selection_score_calculation():
|
|
213
213
|
"""
|
|
214
|
-
|
|
215
|
-
-
|
|
214
|
+
Selection score calculation (complex weights)
|
|
215
|
+
- Feed ร1.15
|
|
216
216
|
- OCR ร1.2
|
|
217
|
-
-
|
|
218
|
-
-
|
|
219
|
-
-
|
|
217
|
+
- Likes ร1.0
|
|
218
|
+
- Bookmarks ร1.0
|
|
219
|
+
- Partnerships ร1.5
|
|
220
220
|
"""
|
|
221
221
|
score = calculate_selection_score(
|
|
222
222
|
feeds=10, # 10 ร 1.15 = 11.5
|
|
@@ -227,73 +227,73 @@ def test_tier_selection_score_calculation():
|
|
|
227
227
|
)
|
|
228
228
|
assert score == 48.5
|
|
229
229
|
|
|
230
|
-
# โ
|
|
230
|
+
# โ Unnecessary Unit Test: Simple CRUD
|
|
231
231
|
def test_get_user_by_id():
|
|
232
|
-
"""Integration Test
|
|
232
|
+
"""Integration Test is sufficient"""
|
|
233
233
|
user = get_user("user-123")
|
|
234
|
-
assert user.id == "user-123" #
|
|
234
|
+
assert user.id == "user-123" # Meaningless
|
|
235
235
|
```
|
|
236
236
|
|
|
237
|
-
### 5. E2E Testing (
|
|
237
|
+
### 5. E2E Testing (Scenario Verification) โญโญ
|
|
238
238
|
|
|
239
|
-
|
|
239
|
+
**Concept**: Test complete scenarios from user perspective
|
|
240
240
|
|
|
241
|
-
|
|
241
|
+
**When**: Only selectively for major user flows
|
|
242
242
|
|
|
243
243
|
```typescript
|
|
244
244
|
// โ
E2E Test: Playwright/Cypress
|
|
245
245
|
test('user can complete full registration flow', async ({ page }) => {
|
|
246
|
-
// 1.
|
|
246
|
+
// 1. Visit homepage
|
|
247
247
|
await page.goto('https://app.example.com');
|
|
248
248
|
|
|
249
|
-
// 2.
|
|
249
|
+
// 2. Click sign up
|
|
250
250
|
await page.click('text=Sign Up');
|
|
251
251
|
|
|
252
|
-
// 3.
|
|
252
|
+
// 3. Fill form
|
|
253
253
|
await page.fill('input[name="email"]', 'test@example.com');
|
|
254
254
|
await page.fill('input[name="username"]', 'testuser');
|
|
255
255
|
await page.fill('input[name="password"]', 'password123');
|
|
256
256
|
|
|
257
|
-
// 4.
|
|
257
|
+
// 4. Submit
|
|
258
258
|
await page.click('button[type="submit"]');
|
|
259
259
|
|
|
260
|
-
// 5.
|
|
260
|
+
// 5. Verify redirect to dashboard
|
|
261
261
|
await expect(page).toHaveURL('/dashboard');
|
|
262
262
|
await expect(page.locator('h1')).toContainText('Welcome, testuser!');
|
|
263
263
|
});
|
|
264
264
|
```
|
|
265
265
|
|
|
266
|
-
##
|
|
266
|
+
## Test Priority Decision Tree
|
|
267
267
|
|
|
268
268
|
```
|
|
269
|
-
|
|
269
|
+
When developing new features:
|
|
270
270
|
|
|
271
|
-
1.
|
|
272
|
-
No โ
|
|
271
|
+
1. Did you define contracts?
|
|
272
|
+
No โ Write contracts first (Pydantic/Zod/Dart class)
|
|
273
273
|
Yes โ โฌ๏ธ
|
|
274
274
|
|
|
275
|
-
2.
|
|
276
|
-
Yes โ Integration Test
|
|
275
|
+
2. Do multiple modules collaborate?
|
|
276
|
+
Yes โ Write Integration Test โญโญโญ
|
|
277
277
|
No โ โฌ๏ธ
|
|
278
278
|
|
|
279
|
-
3.
|
|
280
|
-
Yes โ Unit Test
|
|
279
|
+
3. Is it complex business logic? (complexity > 10)
|
|
280
|
+
Yes โ Write Unit Test โญ
|
|
281
281
|
No โ โฌ๏ธ
|
|
282
282
|
|
|
283
|
-
4.
|
|
284
|
-
Yes โ E2E Test
|
|
285
|
-
No โ
|
|
283
|
+
4. Is it a core user flow?
|
|
284
|
+
Yes โ Write E2E Test โญโญ
|
|
285
|
+
No โ Done โ
|
|
286
286
|
```
|
|
287
287
|
|
|
288
|
-
##
|
|
288
|
+
## TDD Alternative for AI Era: ATDD (AI-Test-Driven Development)
|
|
289
289
|
|
|
290
290
|
```markdown
|
|
291
|
-
#
|
|
291
|
+
# New development flow
|
|
292
292
|
|
|
293
|
-
1.
|
|
294
|
-
"
|
|
293
|
+
1. **Clarify requirements** (Developer)
|
|
294
|
+
"Premium users get 10% discount"
|
|
295
295
|
|
|
296
|
-
2. **
|
|
296
|
+
2. **Define contracts** (Developer)
|
|
297
297
|
interface DiscountRequest {
|
|
298
298
|
userId: string;
|
|
299
299
|
orderTotal: number;
|
|
@@ -305,28 +305,29 @@ test('user can complete full registration flow', async ({ page }) => {
|
|
|
305
305
|
discountRate: number;
|
|
306
306
|
}
|
|
307
307
|
|
|
308
|
-
3.
|
|
308
|
+
3. **Write test scenarios** (Developer or AI)
|
|
309
309
|
test('premium user gets 10% discount', () => {
|
|
310
|
-
// Given:
|
|
311
|
-
// When:
|
|
312
|
-
// Then: 90
|
|
310
|
+
// Given: Premium user, 100 order
|
|
311
|
+
// When: Calculate discount
|
|
312
|
+
// Then: 90 (10% discount)
|
|
313
313
|
})
|
|
314
314
|
|
|
315
|
-
4. **AI
|
|
316
|
-
-
|
|
317
|
-
-
|
|
315
|
+
4. **AI implements** (AI)
|
|
316
|
+
- Generate code following contracts
|
|
317
|
+
- Write code that passes tests
|
|
318
318
|
|
|
319
|
-
5.
|
|
320
|
-
- CI/CD
|
|
319
|
+
5. **Integration test** (Automated)
|
|
320
|
+
- Verify complete scenarios in CI/CD
|
|
321
321
|
|
|
322
|
-
6.
|
|
323
|
-
-
|
|
324
|
-
- SRP
|
|
322
|
+
6. **Refactoring** (AI + Developer)
|
|
323
|
+
- Remove complexity, duplication
|
|
324
|
+
- Verify SRP compliance
|
|
325
325
|
```
|
|
326
326
|
|
|
327
|
-
##
|
|
327
|
+
## Language-specific Tools
|
|
328
328
|
|
|
329
329
|
### Python
|
|
330
|
+
|
|
330
331
|
```bash
|
|
331
332
|
# Contract Testing
|
|
332
333
|
pip install pydantic
|
|
@@ -342,6 +343,7 @@ pip install pytest-cov
|
|
|
342
343
|
```
|
|
343
344
|
|
|
344
345
|
### TypeScript/JavaScript
|
|
346
|
+
|
|
345
347
|
```bash
|
|
346
348
|
# Contract Testing
|
|
347
349
|
npm install zod
|
|
@@ -357,6 +359,7 @@ npm install playwright
|
|
|
357
359
|
```
|
|
358
360
|
|
|
359
361
|
### Dart/Flutter
|
|
362
|
+
|
|
360
363
|
```bash
|
|
361
364
|
# Integration Testing
|
|
362
365
|
flutter pub add integration_test
|
|
@@ -368,29 +371,29 @@ flutter test
|
|
|
368
371
|
flutter drive --target=test_driver/app.dart
|
|
369
372
|
```
|
|
370
373
|
|
|
371
|
-
##
|
|
374
|
+
## Anti-patterns
|
|
372
375
|
|
|
373
376
|
```python
|
|
374
|
-
# โ
|
|
377
|
+
# โ Testing implementation details (fragile)
|
|
375
378
|
def test_internal_cache_structure():
|
|
376
379
|
service = UserService()
|
|
377
|
-
assert service._cache == {} #
|
|
380
|
+
assert service._cache == {} # Depends on internal implementation
|
|
378
381
|
|
|
379
|
-
# โ
|
|
382
|
+
# โ
Testing public API (robust)
|
|
380
383
|
def test_user_data_is_cached_after_first_call():
|
|
381
384
|
service = UserService()
|
|
382
385
|
user1 = service.get_user("123")
|
|
383
386
|
user2 = service.get_user("123")
|
|
384
|
-
assert user1 is user2 #
|
|
387
|
+
assert user1 is user2 # Only verify behavior
|
|
385
388
|
```
|
|
386
389
|
|
|
387
390
|
```typescript
|
|
388
|
-
// โ
|
|
391
|
+
// โ Unit tests for every function (excessive)
|
|
389
392
|
test('add function adds two numbers', () => {
|
|
390
|
-
expect(add(1, 2)).toBe(3); //
|
|
393
|
+
expect(add(1, 2)).toBe(3); // Meaningless
|
|
391
394
|
});
|
|
392
395
|
|
|
393
|
-
// โ
|
|
396
|
+
// โ
Only test complex logic
|
|
394
397
|
test('calculate shipping cost with multiple conditions', () => {
|
|
395
398
|
const cost = calculateShipping({
|
|
396
399
|
weight: 10,
|
|
@@ -398,40 +401,40 @@ test('calculate shipping cost with multiple conditions', () => {
|
|
|
398
401
|
isPremium: true,
|
|
399
402
|
isExpress: false,
|
|
400
403
|
});
|
|
401
|
-
expect(cost).toBe(45); //
|
|
404
|
+
expect(cost).toBe(45); // Verify complex rules
|
|
402
405
|
});
|
|
403
406
|
```
|
|
404
407
|
|
|
405
|
-
##
|
|
408
|
+
## Test Coverage Goals
|
|
406
409
|
|
|
407
410
|
```markdown
|
|
408
|
-
#
|
|
411
|
+
# Realistic goals
|
|
409
412
|
|
|
410
|
-
- Contract Coverage: 100% (
|
|
411
|
-
- Integration Coverage: 80% (
|
|
412
|
-
- Unit Coverage:
|
|
413
|
-
- E2E Coverage: 20-30% (
|
|
413
|
+
- Contract Coverage: 100% (All APIs have schema definitions)
|
|
414
|
+
- Integration Coverage: 80% (Major business flows)
|
|
415
|
+
- Unit Coverage: Selective (Complex logic only)
|
|
416
|
+
- E2E Coverage: 20-30% (Core user flows)
|
|
414
417
|
|
|
415
|
-
# โ
|
|
416
|
-
- 100% Unit Test Coverage (
|
|
417
|
-
-
|
|
418
|
-
-
|
|
418
|
+
# โ Avoid
|
|
419
|
+
- 100% Unit Test Coverage (waste of time)
|
|
420
|
+
- Unit Tests for simple CRUD (Integration is sufficient)
|
|
421
|
+
- Manual testing all edge cases (use Property-based)
|
|
419
422
|
```
|
|
420
423
|
|
|
421
|
-
##
|
|
424
|
+
## Key Summary
|
|
422
425
|
|
|
423
426
|
```markdown
|
|
424
|
-
AI
|
|
425
|
-
|
|
426
|
-
1. โ
Contract-First (
|
|
427
|
-
2. โ
Integration Testing (
|
|
428
|
-
3. โ ๏ธ Unit Testing (
|
|
429
|
-
4. โ
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
-
|
|
433
|
-
-
|
|
434
|
-
-
|
|
435
|
-
-
|
|
436
|
-
-
|
|
427
|
+
AI Era Testing Strategy:
|
|
428
|
+
|
|
429
|
+
1. โ
Contract-First (types/schemas first)
|
|
430
|
+
2. โ
Integration Testing (real scenarios)
|
|
431
|
+
3. โ ๏ธ Unit Testing (complex logic only)
|
|
432
|
+
4. โ Traditional TDD (inefficient in AI era)
|
|
433
|
+
|
|
434
|
+
Goals:
|
|
435
|
+
- Single Responsibility (SRP)
|
|
436
|
+
- No Duplication (DRY)
|
|
437
|
+
- Reusability
|
|
438
|
+
- Low Complexity
|
|
439
|
+
- Fast Feedback
|
|
437
440
|
```
|