@su-record/vibe 2.3.0 → 2.3.2

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 (98) hide show
  1. package/.claude/settings.json +35 -35
  2. package/.claude/settings.local.json +24 -25
  3. package/.claude/vibe/constitution.md +184 -184
  4. package/.claude/vibe/rules/core/communication-guide.md +104 -104
  5. package/.claude/vibe/rules/core/development-philosophy.md +52 -52
  6. package/.claude/vibe/rules/core/quick-start.md +120 -120
  7. package/.claude/vibe/rules/languages/dart-flutter.md +509 -509
  8. package/.claude/vibe/rules/languages/go.md +396 -396
  9. package/.claude/vibe/rules/languages/java-spring.md +586 -586
  10. package/.claude/vibe/rules/languages/kotlin-android.md +491 -491
  11. package/.claude/vibe/rules/languages/python-django.md +371 -371
  12. package/.claude/vibe/rules/languages/python-fastapi.md +386 -386
  13. package/.claude/vibe/rules/languages/rust.md +425 -425
  14. package/.claude/vibe/rules/languages/swift-ios.md +516 -516
  15. package/.claude/vibe/rules/languages/typescript-nextjs.md +441 -441
  16. package/.claude/vibe/rules/languages/typescript-node.md +375 -375
  17. package/.claude/vibe/rules/languages/typescript-nuxt.md +521 -521
  18. package/.claude/vibe/rules/languages/typescript-react-native.md +446 -446
  19. package/.claude/vibe/rules/languages/typescript-react.md +525 -525
  20. package/.claude/vibe/rules/languages/typescript-vue.md +353 -353
  21. package/.claude/vibe/rules/quality/bdd-contract-testing.md +388 -388
  22. package/.claude/vibe/rules/quality/checklist.md +276 -276
  23. package/.claude/vibe/rules/quality/testing-strategy.md +437 -437
  24. package/.claude/vibe/rules/standards/anti-patterns.md +369 -369
  25. package/.claude/vibe/rules/standards/code-structure.md +291 -291
  26. package/.claude/vibe/rules/standards/complexity-metrics.md +312 -312
  27. package/.claude/vibe/rules/standards/naming-conventions.md +198 -198
  28. package/.claude/vibe/setup.sh +31 -31
  29. package/.claude/vibe/templates/constitution-template.md +184 -184
  30. package/.claude/vibe/templates/contract-backend-template.md +517 -517
  31. package/.claude/vibe/templates/contract-frontend-template.md +594 -594
  32. package/.claude/vibe/templates/feature-template.md +96 -96
  33. package/.claude/vibe/templates/spec-template.md +199 -199
  34. package/CLAUDE.md +345 -323
  35. package/LICENSE +21 -21
  36. package/README.md +744 -724
  37. package/agents/compounder.md +261 -261
  38. package/agents/diagrammer.md +178 -178
  39. package/agents/e2e-tester.md +266 -266
  40. package/agents/explorer.md +48 -48
  41. package/agents/implementer.md +53 -53
  42. package/agents/research/best-practices-agent.md +139 -139
  43. package/agents/research/codebase-patterns-agent.md +147 -147
  44. package/agents/research/framework-docs-agent.md +181 -181
  45. package/agents/research/security-advisory-agent.md +167 -167
  46. package/agents/review/architecture-reviewer.md +107 -107
  47. package/agents/review/complexity-reviewer.md +116 -116
  48. package/agents/review/data-integrity-reviewer.md +88 -88
  49. package/agents/review/git-history-reviewer.md +103 -103
  50. package/agents/review/performance-reviewer.md +86 -86
  51. package/agents/review/python-reviewer.md +152 -152
  52. package/agents/review/rails-reviewer.md +139 -139
  53. package/agents/review/react-reviewer.md +144 -144
  54. package/agents/review/security-reviewer.md +80 -80
  55. package/agents/review/simplicity-reviewer.md +140 -140
  56. package/agents/review/test-coverage-reviewer.md +116 -116
  57. package/agents/review/typescript-reviewer.md +127 -127
  58. package/agents/searcher.md +54 -54
  59. package/agents/simplifier.md +119 -119
  60. package/agents/tester.md +49 -49
  61. package/agents/ui-previewer.md +137 -137
  62. package/commands/vibe.analyze.md +245 -180
  63. package/commands/vibe.reason.md +223 -183
  64. package/commands/vibe.review.md +200 -136
  65. package/commands/vibe.run.md +838 -836
  66. package/commands/vibe.spec.md +419 -383
  67. package/commands/vibe.utils.md +101 -101
  68. package/commands/vibe.verify.md +282 -241
  69. package/dist/cli/index.js +385 -385
  70. package/dist/lib/MemoryManager.d.ts.map +1 -1
  71. package/dist/lib/MemoryManager.js +119 -114
  72. package/dist/lib/MemoryManager.js.map +1 -1
  73. package/dist/lib/PythonParser.js +108 -108
  74. package/dist/lib/gemini-mcp.js +15 -15
  75. package/dist/lib/gemini-oauth.js +35 -35
  76. package/dist/lib/gpt-mcp.js +17 -17
  77. package/dist/lib/gpt-oauth.js +44 -44
  78. package/dist/tools/analytics/getUsageAnalytics.js +12 -12
  79. package/dist/tools/index.d.ts +50 -0
  80. package/dist/tools/index.d.ts.map +1 -0
  81. package/dist/tools/index.js +61 -0
  82. package/dist/tools/index.js.map +1 -0
  83. package/dist/tools/memory/createMemoryTimeline.js +10 -10
  84. package/dist/tools/memory/getMemoryGraph.js +12 -12
  85. package/dist/tools/memory/getSessionContext.js +9 -9
  86. package/dist/tools/memory/linkMemories.js +14 -14
  87. package/dist/tools/memory/listMemories.js +4 -4
  88. package/dist/tools/memory/recallMemory.js +4 -4
  89. package/dist/tools/memory/saveMemory.js +4 -4
  90. package/dist/tools/memory/searchMemoriesAdvanced.js +22 -22
  91. package/dist/tools/planning/generatePrd.js +46 -46
  92. package/dist/tools/prompt/enhancePromptGemini.js +160 -160
  93. package/dist/tools/reasoning/applyReasoningFramework.js +56 -56
  94. package/dist/tools/semantic/analyzeDependencyGraph.js +12 -12
  95. package/hooks/hooks.json +121 -103
  96. package/package.json +73 -69
  97. package/skills/git-worktree.md +178 -178
  98. package/skills/priority-todos.md +236 -236
@@ -1,437 +1,437 @@
1
- # 🧪 AI 시대 테스트 전략
2
-
3
- ## 핵심 원칙
4
-
5
- ```markdown
6
- ✅ 단일 책임 (SRP)
7
- ✅ 중복 코드 제거 (DRY)
8
- ✅ 재사용성 (Reusability)
9
- ✅ 낮은 복잡도 (Low Complexity)
10
- ✅ 계약 우선 설계 (Contract-First)
11
- ```
12
-
13
- ## AI 주도 개발에서의 테스트 우선순위
14
-
15
- ### 1. Contract Testing (최우선) ⭐⭐⭐
16
-
17
- **개념**: 코드 작성 전에 **타입/스키마로 계약을 정의**
18
-
19
- **이유**: AI가 계약을 따라 구현하므로, 타입 안전성이 자동 보장됨
20
-
21
- #### Python (Pydantic)
22
-
23
- ```python
24
- # 계약 정의 (AI가 이를 따라 구현)
25
- from pydantic import BaseModel, Field, EmailStr
26
-
27
- class CreateUserRequest(BaseModel):
28
- """사용자 생성 계약"""
29
- email: EmailStr
30
- username: str = Field(min_length=3, max_length=50)
31
- password: str = Field(min_length=8)
32
- age: int = Field(ge=0, le=150)
33
-
34
- class UserResponse(BaseModel):
35
- """사용자 응답 계약"""
36
- id: str
37
- email: str
38
- username: str
39
- created_at: str
40
-
41
- # AI가 이 계약을 위반할 수 없음 (자동 검증)
42
- ```
43
-
44
- #### TypeScript
45
-
46
- ```typescript
47
- // 계약 정의
48
- interface CreateUserRequest {
49
- email: string;
50
- username: string; // 3-50자
51
- password: string; // 최소 8자
52
- age: number; // 0-150
53
- }
54
-
55
- interface UserResponse {
56
- id: string;
57
- email: string;
58
- username: string;
59
- createdAt: string;
60
- }
61
-
62
- // Zod로 런타임 검증
63
- import { z } from 'zod';
64
-
65
- const createUserSchema = z.object({
66
- email: z.string().email(),
67
- username: z.string().min(3).max(50),
68
- password: z.string().min(8),
69
- age: z.number().min(0).max(150),
70
- });
71
- ```
72
-
73
- #### Dart (Flutter)
74
-
75
- ```dart
76
- // 계약 정의
77
- class CreateUserRequest {
78
- const CreateUserRequest({
79
- required this.email,
80
- required this.username,
81
- required this.password,
82
- required this.age,
83
- });
84
-
85
- final String email;
86
- final String username; // 3-50자
87
- final String password; // 최소 8자
88
- final int age; // 0-150
89
-
90
- // JSON 직렬화 (계약 강제)
91
- Map<String, dynamic> toJson() => {
92
- 'email': email,
93
- 'username': username,
94
- 'password': password,
95
- 'age': age,
96
- };
97
- }
98
- ```
99
-
100
- ### 2. Integration Testing (높음) ⭐⭐⭐
101
-
102
- **개념**: 여러 모듈이 함께 작동하는 **실제 시나리오 테스트**
103
-
104
- **이유**: AI가 놓친 모듈 간 상호작용 오류를 발견
105
-
106
- ```python
107
- # ✅ 통합 테스트: 실제 비즈니스 흐름
108
- @pytest.mark.asyncio
109
- async def test_user_registration_flow():
110
- """
111
- 시나리오: 신규 사용자 가입
112
- 1. 이메일 중복 체크
113
- 2. 사용자 생성
114
- 3. 환영 이메일 발송
115
- 4. 기본 설정 생성
116
- """
117
- # Given: 신규 사용자 정보
118
- request = CreateUserRequest(
119
- email="new@example.com",
120
- username="newuser",
121
- password="password123",
122
- age=25,
123
- )
124
-
125
- # When: 회원가입 API 호출
126
- response = await client.post("/api/users", json=request.dict())
127
-
128
- # Then: 사용자 생성 성공
129
- assert response.status_code == 201
130
- data = response.json()
131
- assert data["email"] == "new@example.com"
132
-
133
- # And: 환영 이메일 발송 확인
134
- assert email_service.sent_count == 1
135
-
136
- # And: 기본 설정 생성 확인
137
- settings = await get_user_settings(data["id"])
138
- assert settings is not None
139
- ```
140
-
141
- ```typescript
142
- // ✅ 통합 테스트: React 컴포넌트 + API
143
- import { render, screen, waitFor } from '@testing-library/react';
144
- import userEvent from '@testing-library/user-event';
145
- import { UserRegistration } from './UserRegistration';
146
-
147
- test('user can register successfully', async () => {
148
- // Given: 회원가입 폼 렌더링
149
- render(<UserRegistration />);
150
-
151
- // When: 사용자가 폼 입력
152
- await userEvent.type(screen.getByLabelText('Email'), 'new@example.com');
153
- await userEvent.type(screen.getByLabelText('Username'), 'newuser');
154
- await userEvent.type(screen.getByLabelText('Password'), 'password123');
155
- await userEvent.click(screen.getByRole('button', { name: 'Sign Up' }));
156
-
157
- // Then: 성공 메시지 표시
158
- await waitFor(() => {
159
- expect(screen.getByText('Welcome!')).toBeInTheDocument();
160
- });
161
- });
162
- ```
163
-
164
- ### 3. Property-Based Testing (중간) ⭐⭐
165
-
166
- **개념**: 입력 범위 전체를 **자동 생성하여 테스트**
167
-
168
- **이유**: AI가 생각 못한 엣지 케이스를 자동으로 발견
169
-
170
- ```python
171
- # ✅ Property-based testing (Hypothesis)
172
- from hypothesis import given, strategies as st
173
-
174
- @given(
175
- age=st.integers(min_value=0, max_value=150),
176
- email=st.emails(),
177
- username=st.text(min_size=3, max_size=50),
178
- )
179
- def test_user_creation_with_any_valid_input(age, email, username):
180
- """모든 유효한 입력으로 사용자 생성 가능"""
181
- user = create_user(email=email, username=username, age=age)
182
- assert user.age == age
183
- assert user.email == email
184
- ```
185
-
186
- ```typescript
187
- // ✅ Property-based testing (fast-check)
188
- import fc from 'fast-check';
189
-
190
- test('discount calculation always returns valid percentage', () => {
191
- fc.assert(
192
- fc.property(
193
- fc.float({ min: 0, max: 10000 }), // 가격
194
- fc.float({ min: 0, max: 1 }), // 할인율
195
- (price, rate) => {
196
- const discount = calculateDiscount(price, rate);
197
- return discount >= 0 && discount <= price;
198
- }
199
- )
200
- );
201
- });
202
- ```
203
-
204
- ### 4. Unit Testing (낮음, 선택적) ⭐
205
-
206
- **개념**: 개별 함수/메서드 테스트
207
-
208
- **언제 작성**: **복잡한 비즈니스 로직만** 선택적으로
209
-
210
- ```python
211
- # ✅ Unit Test: 복잡한 비즈니스 규칙
212
- def test_tier_selection_score_calculation():
213
- """
214
- 대장금 선발 점수 계산 (복잡한 가중치)
215
- - 피드 ×1.15
216
- - OCR ×1.2
217
- - 좋아요 ×1.0
218
- - 북마크 ×1.0
219
- - 연계 ×1.5
220
- """
221
- score = calculate_selection_score(
222
- feeds=10, # 10 × 1.15 = 11.5
223
- ocr_count=5, # 5 × 1.2 = 6
224
- likes=20, # 20 × 1.0 = 20
225
- bookmarks=8, # 8 × 1.0 = 8
226
- partnerships=2, # 2 × 1.5 = 3
227
- )
228
- assert score == 48.5
229
-
230
- # ❌ 불필요한 Unit Test: 단순 CRUD
231
- def test_get_user_by_id():
232
- """Integration Test로 충분"""
233
- user = get_user("user-123")
234
- assert user.id == "user-123" # 의미 없음
235
- ```
236
-
237
- ### 5. E2E Testing (시나리오 검증) ⭐⭐
238
-
239
- **개념**: 사용자 관점의 전체 시나리오 테스트
240
-
241
- **언제**: 주요 사용자 플로우만 선택적으로
242
-
243
- ```typescript
244
- // ✅ E2E Test: Playwright/Cypress
245
- test('user can complete full registration flow', async ({ page }) => {
246
- // 1. 홈페이지 접속
247
- await page.goto('https://app.example.com');
248
-
249
- // 2. 회원가입 클릭
250
- await page.click('text=Sign Up');
251
-
252
- // 3. 폼 입력
253
- await page.fill('input[name="email"]', 'test@example.com');
254
- await page.fill('input[name="username"]', 'testuser');
255
- await page.fill('input[name="password"]', 'password123');
256
-
257
- // 4. 제출
258
- await page.click('button[type="submit"]');
259
-
260
- // 5. 대시보드로 리다이렉트 확인
261
- await expect(page).toHaveURL('/dashboard');
262
- await expect(page.locator('h1')).toContainText('Welcome, testuser!');
263
- });
264
- ```
265
-
266
- ## 테스트 우선순위 결정 트리
267
-
268
- ```
269
- 새 기능 개발 시:
270
-
271
- 1. Contract 정의했는가?
272
- No → Contract 먼저 작성 (Pydantic/Zod/Dart class)
273
- Yes → ⬇️
274
-
275
- 2. 여러 모듈이 협력하는가?
276
- Yes → Integration Test 작성 ⭐⭐⭐
277
- No → ⬇️
278
-
279
- 3. 복잡한 비즈니스 로직인가? (복잡도 > 10)
280
- Yes → Unit Test 작성 ⭐
281
- No → ⬇️
282
-
283
- 4. 핵심 사용자 플로우인가?
284
- Yes → E2E Test 작성 ⭐⭐
285
- No → 완료 ✅
286
- ```
287
-
288
- ## AI 시대의 TDD 대안: ATDD (AI-Test-Driven Development)
289
-
290
- ```markdown
291
- # 새로운 개발 흐름
292
-
293
- 1. **요구사항 명확화** (개발자)
294
- "프리미엄 사용자는 10% 할인을 받는다"
295
-
296
- 2. **Contract 정의** (개발자)
297
- interface DiscountRequest {
298
- userId: string;
299
- orderTotal: number;
300
- }
301
-
302
- interface DiscountResponse {
303
- originalPrice: number;
304
- discountedPrice: number;
305
- discountRate: number;
306
- }
307
-
308
- 3. **테스트 시나리오 작성** (개발자 or AI)
309
- test('premium user gets 10% discount', () => {
310
- // Given: 프리미엄 유저, 100원 주문
311
- // When: 할인 계산
312
- // Then: 90원 (10% 할인)
313
- })
314
-
315
- 4. **AI가 구현** (AI)
316
- - Contract를 따라 코드 생성
317
- - 테스트 통과하는 코드 작성
318
-
319
- 5. **통합 테스트** (자동)
320
- - CI/CD에서 전체 시나리오 검증
321
-
322
- 6. **리팩토링** (AI + 개발자)
323
- - 복잡도, 중복 제거
324
- - SRP 준수 확인
325
- ```
326
-
327
- ## 언어별 도구
328
-
329
- ### Python
330
- ```bash
331
- # Contract Testing
332
- pip install pydantic
333
-
334
- # Integration Testing
335
- pip install pytest pytest-asyncio httpx
336
-
337
- # Property-Based Testing
338
- pip install hypothesis
339
-
340
- # Coverage
341
- pip install pytest-cov
342
- ```
343
-
344
- ### TypeScript/JavaScript
345
- ```bash
346
- # Contract Testing
347
- npm install zod
348
-
349
- # Integration Testing
350
- npm install @testing-library/react @testing-library/user-event
351
-
352
- # Property-Based Testing
353
- npm install fast-check
354
-
355
- # E2E Testing
356
- npm install playwright
357
- ```
358
-
359
- ### Dart/Flutter
360
- ```bash
361
- # Integration Testing
362
- flutter pub add integration_test
363
-
364
- # Widget Testing
365
- flutter test
366
-
367
- # E2E Testing (Flutter Driver)
368
- flutter drive --target=test_driver/app.dart
369
- ```
370
-
371
- ## 안티패턴
372
-
373
- ```python
374
- # ❌ 구현 세부사항 테스트 (깨지기 쉬움)
375
- def test_internal_cache_structure():
376
- service = UserService()
377
- assert service._cache == {} # 내부 구현에 의존
378
-
379
- # ✅ 공개 API 테스트 (견고함)
380
- def test_user_data_is_cached_after_first_call():
381
- service = UserService()
382
- user1 = service.get_user("123")
383
- user2 = service.get_user("123")
384
- assert user1 is user2 # 동작만 검증
385
- ```
386
-
387
- ```typescript
388
- // ❌ 모든 함수에 Unit Test (과도함)
389
- test('add function adds two numbers', () => {
390
- expect(add(1, 2)).toBe(3); // 의미 없음
391
- });
392
-
393
- // ✅ 복잡한 로직만 테스트
394
- test('calculate shipping cost with multiple conditions', () => {
395
- const cost = calculateShipping({
396
- weight: 10,
397
- distance: 500,
398
- isPremium: true,
399
- isExpress: false,
400
- });
401
- expect(cost).toBe(45); // 복잡한 규칙 검증
402
- });
403
- ```
404
-
405
- ## 테스트 커버리지 목표
406
-
407
- ```markdown
408
- # 현실적인 목표
409
-
410
- - Contract Coverage: 100% (모든 API는 스키마 정의)
411
- - Integration Coverage: 80% (주요 비즈니스 흐름)
412
- - Unit Coverage: 선택적 (복잡한 로직만)
413
- - E2E Coverage: 20-30% (핵심 사용자 플로우)
414
-
415
- # ❌ 피해야 할 것
416
- - 100% Unit Test Coverage (시간 낭비)
417
- - 단순 CRUD에 Unit Test (Integration으로 충분)
418
- - 모든 엣지 케이스 수동 테스트 (Property-based 사용)
419
- ```
420
-
421
- ## 핵심 요약
422
-
423
- ```markdown
424
- AI 시대 테스트 전략:
425
-
426
- 1. ✅ Contract-First (타입/스키마 먼저)
427
- 2. ✅ Integration Testing (실제 시나리오)
428
- 3. ⚠️ Unit Testing (복잡한 로직만)
429
- 4. ❌ 전통적 TDD (AI 시대엔 비효율)
430
-
431
- 목표:
432
- - 단일 책임 (SRP)
433
- - 중복 제거 (DRY)
434
- - 재사용성
435
- - 낮은 복잡도
436
- - 빠른 피드백
437
- ```
1
+ # 🧪 AI 시대 테스트 전략
2
+
3
+ ## 핵심 원칙
4
+
5
+ ```markdown
6
+ ✅ 단일 책임 (SRP)
7
+ ✅ 중복 코드 제거 (DRY)
8
+ ✅ 재사용성 (Reusability)
9
+ ✅ 낮은 복잡도 (Low Complexity)
10
+ ✅ 계약 우선 설계 (Contract-First)
11
+ ```
12
+
13
+ ## AI 주도 개발에서의 테스트 우선순위
14
+
15
+ ### 1. Contract Testing (최우선) ⭐⭐⭐
16
+
17
+ **개념**: 코드 작성 전에 **타입/스키마로 계약을 정의**
18
+
19
+ **이유**: AI가 계약을 따라 구현하므로, 타입 안전성이 자동 보장됨
20
+
21
+ #### Python (Pydantic)
22
+
23
+ ```python
24
+ # 계약 정의 (AI가 이를 따라 구현)
25
+ from pydantic import BaseModel, Field, EmailStr
26
+
27
+ class CreateUserRequest(BaseModel):
28
+ """사용자 생성 계약"""
29
+ email: EmailStr
30
+ username: str = Field(min_length=3, max_length=50)
31
+ password: str = Field(min_length=8)
32
+ age: int = Field(ge=0, le=150)
33
+
34
+ class UserResponse(BaseModel):
35
+ """사용자 응답 계약"""
36
+ id: str
37
+ email: str
38
+ username: str
39
+ created_at: str
40
+
41
+ # AI가 이 계약을 위반할 수 없음 (자동 검증)
42
+ ```
43
+
44
+ #### TypeScript
45
+
46
+ ```typescript
47
+ // 계약 정의
48
+ interface CreateUserRequest {
49
+ email: string;
50
+ username: string; // 3-50자
51
+ password: string; // 최소 8자
52
+ age: number; // 0-150
53
+ }
54
+
55
+ interface UserResponse {
56
+ id: string;
57
+ email: string;
58
+ username: string;
59
+ createdAt: string;
60
+ }
61
+
62
+ // Zod로 런타임 검증
63
+ import { z } from 'zod';
64
+
65
+ const createUserSchema = z.object({
66
+ email: z.string().email(),
67
+ username: z.string().min(3).max(50),
68
+ password: z.string().min(8),
69
+ age: z.number().min(0).max(150),
70
+ });
71
+ ```
72
+
73
+ #### Dart (Flutter)
74
+
75
+ ```dart
76
+ // 계약 정의
77
+ class CreateUserRequest {
78
+ const CreateUserRequest({
79
+ required this.email,
80
+ required this.username,
81
+ required this.password,
82
+ required this.age,
83
+ });
84
+
85
+ final String email;
86
+ final String username; // 3-50자
87
+ final String password; // 최소 8자
88
+ final int age; // 0-150
89
+
90
+ // JSON 직렬화 (계약 강제)
91
+ Map<String, dynamic> toJson() => {
92
+ 'email': email,
93
+ 'username': username,
94
+ 'password': password,
95
+ 'age': age,
96
+ };
97
+ }
98
+ ```
99
+
100
+ ### 2. Integration Testing (높음) ⭐⭐⭐
101
+
102
+ **개념**: 여러 모듈이 함께 작동하는 **실제 시나리오 테스트**
103
+
104
+ **이유**: AI가 놓친 모듈 간 상호작용 오류를 발견
105
+
106
+ ```python
107
+ # ✅ 통합 테스트: 실제 비즈니스 흐름
108
+ @pytest.mark.asyncio
109
+ async def test_user_registration_flow():
110
+ """
111
+ 시나리오: 신규 사용자 가입
112
+ 1. 이메일 중복 체크
113
+ 2. 사용자 생성
114
+ 3. 환영 이메일 발송
115
+ 4. 기본 설정 생성
116
+ """
117
+ # Given: 신규 사용자 정보
118
+ request = CreateUserRequest(
119
+ email="new@example.com",
120
+ username="newuser",
121
+ password="password123",
122
+ age=25,
123
+ )
124
+
125
+ # When: 회원가입 API 호출
126
+ response = await client.post("/api/users", json=request.dict())
127
+
128
+ # Then: 사용자 생성 성공
129
+ assert response.status_code == 201
130
+ data = response.json()
131
+ assert data["email"] == "new@example.com"
132
+
133
+ # And: 환영 이메일 발송 확인
134
+ assert email_service.sent_count == 1
135
+
136
+ # And: 기본 설정 생성 확인
137
+ settings = await get_user_settings(data["id"])
138
+ assert settings is not None
139
+ ```
140
+
141
+ ```typescript
142
+ // ✅ 통합 테스트: React 컴포넌트 + API
143
+ import { render, screen, waitFor } from '@testing-library/react';
144
+ import userEvent from '@testing-library/user-event';
145
+ import { UserRegistration } from './UserRegistration';
146
+
147
+ test('user can register successfully', async () => {
148
+ // Given: 회원가입 폼 렌더링
149
+ render(<UserRegistration />);
150
+
151
+ // When: 사용자가 폼 입력
152
+ await userEvent.type(screen.getByLabelText('Email'), 'new@example.com');
153
+ await userEvent.type(screen.getByLabelText('Username'), 'newuser');
154
+ await userEvent.type(screen.getByLabelText('Password'), 'password123');
155
+ await userEvent.click(screen.getByRole('button', { name: 'Sign Up' }));
156
+
157
+ // Then: 성공 메시지 표시
158
+ await waitFor(() => {
159
+ expect(screen.getByText('Welcome!')).toBeInTheDocument();
160
+ });
161
+ });
162
+ ```
163
+
164
+ ### 3. Property-Based Testing (중간) ⭐⭐
165
+
166
+ **개념**: 입력 범위 전체를 **자동 생성하여 테스트**
167
+
168
+ **이유**: AI가 생각 못한 엣지 케이스를 자동으로 발견
169
+
170
+ ```python
171
+ # ✅ Property-based testing (Hypothesis)
172
+ from hypothesis import given, strategies as st
173
+
174
+ @given(
175
+ age=st.integers(min_value=0, max_value=150),
176
+ email=st.emails(),
177
+ username=st.text(min_size=3, max_size=50),
178
+ )
179
+ def test_user_creation_with_any_valid_input(age, email, username):
180
+ """모든 유효한 입력으로 사용자 생성 가능"""
181
+ user = create_user(email=email, username=username, age=age)
182
+ assert user.age == age
183
+ assert user.email == email
184
+ ```
185
+
186
+ ```typescript
187
+ // ✅ Property-based testing (fast-check)
188
+ import fc from 'fast-check';
189
+
190
+ test('discount calculation always returns valid percentage', () => {
191
+ fc.assert(
192
+ fc.property(
193
+ fc.float({ min: 0, max: 10000 }), // 가격
194
+ fc.float({ min: 0, max: 1 }), // 할인율
195
+ (price, rate) => {
196
+ const discount = calculateDiscount(price, rate);
197
+ return discount >= 0 && discount <= price;
198
+ }
199
+ )
200
+ );
201
+ });
202
+ ```
203
+
204
+ ### 4. Unit Testing (낮음, 선택적) ⭐
205
+
206
+ **개념**: 개별 함수/메서드 테스트
207
+
208
+ **언제 작성**: **복잡한 비즈니스 로직만** 선택적으로
209
+
210
+ ```python
211
+ # ✅ Unit Test: 복잡한 비즈니스 규칙
212
+ def test_tier_selection_score_calculation():
213
+ """
214
+ 대장금 선발 점수 계산 (복잡한 가중치)
215
+ - 피드 ×1.15
216
+ - OCR ×1.2
217
+ - 좋아요 ×1.0
218
+ - 북마크 ×1.0
219
+ - 연계 ×1.5
220
+ """
221
+ score = calculate_selection_score(
222
+ feeds=10, # 10 × 1.15 = 11.5
223
+ ocr_count=5, # 5 × 1.2 = 6
224
+ likes=20, # 20 × 1.0 = 20
225
+ bookmarks=8, # 8 × 1.0 = 8
226
+ partnerships=2, # 2 × 1.5 = 3
227
+ )
228
+ assert score == 48.5
229
+
230
+ # ❌ 불필요한 Unit Test: 단순 CRUD
231
+ def test_get_user_by_id():
232
+ """Integration Test로 충분"""
233
+ user = get_user("user-123")
234
+ assert user.id == "user-123" # 의미 없음
235
+ ```
236
+
237
+ ### 5. E2E Testing (시나리오 검증) ⭐⭐
238
+
239
+ **개념**: 사용자 관점의 전체 시나리오 테스트
240
+
241
+ **언제**: 주요 사용자 플로우만 선택적으로
242
+
243
+ ```typescript
244
+ // ✅ E2E Test: Playwright/Cypress
245
+ test('user can complete full registration flow', async ({ page }) => {
246
+ // 1. 홈페이지 접속
247
+ await page.goto('https://app.example.com');
248
+
249
+ // 2. 회원가입 클릭
250
+ await page.click('text=Sign Up');
251
+
252
+ // 3. 폼 입력
253
+ await page.fill('input[name="email"]', 'test@example.com');
254
+ await page.fill('input[name="username"]', 'testuser');
255
+ await page.fill('input[name="password"]', 'password123');
256
+
257
+ // 4. 제출
258
+ await page.click('button[type="submit"]');
259
+
260
+ // 5. 대시보드로 리다이렉트 확인
261
+ await expect(page).toHaveURL('/dashboard');
262
+ await expect(page.locator('h1')).toContainText('Welcome, testuser!');
263
+ });
264
+ ```
265
+
266
+ ## 테스트 우선순위 결정 트리
267
+
268
+ ```
269
+ 새 기능 개발 시:
270
+
271
+ 1. Contract 정의했는가?
272
+ No → Contract 먼저 작성 (Pydantic/Zod/Dart class)
273
+ Yes → ⬇️
274
+
275
+ 2. 여러 모듈이 협력하는가?
276
+ Yes → Integration Test 작성 ⭐⭐⭐
277
+ No → ⬇️
278
+
279
+ 3. 복잡한 비즈니스 로직인가? (복잡도 > 10)
280
+ Yes → Unit Test 작성 ⭐
281
+ No → ⬇️
282
+
283
+ 4. 핵심 사용자 플로우인가?
284
+ Yes → E2E Test 작성 ⭐⭐
285
+ No → 완료 ✅
286
+ ```
287
+
288
+ ## AI 시대의 TDD 대안: ATDD (AI-Test-Driven Development)
289
+
290
+ ```markdown
291
+ # 새로운 개발 흐름
292
+
293
+ 1. **요구사항 명확화** (개발자)
294
+ "프리미엄 사용자는 10% 할인을 받는다"
295
+
296
+ 2. **Contract 정의** (개발자)
297
+ interface DiscountRequest {
298
+ userId: string;
299
+ orderTotal: number;
300
+ }
301
+
302
+ interface DiscountResponse {
303
+ originalPrice: number;
304
+ discountedPrice: number;
305
+ discountRate: number;
306
+ }
307
+
308
+ 3. **테스트 시나리오 작성** (개발자 or AI)
309
+ test('premium user gets 10% discount', () => {
310
+ // Given: 프리미엄 유저, 100원 주문
311
+ // When: 할인 계산
312
+ // Then: 90원 (10% 할인)
313
+ })
314
+
315
+ 4. **AI가 구현** (AI)
316
+ - Contract를 따라 코드 생성
317
+ - 테스트 통과하는 코드 작성
318
+
319
+ 5. **통합 테스트** (자동)
320
+ - CI/CD에서 전체 시나리오 검증
321
+
322
+ 6. **리팩토링** (AI + 개발자)
323
+ - 복잡도, 중복 제거
324
+ - SRP 준수 확인
325
+ ```
326
+
327
+ ## 언어별 도구
328
+
329
+ ### Python
330
+ ```bash
331
+ # Contract Testing
332
+ pip install pydantic
333
+
334
+ # Integration Testing
335
+ pip install pytest pytest-asyncio httpx
336
+
337
+ # Property-Based Testing
338
+ pip install hypothesis
339
+
340
+ # Coverage
341
+ pip install pytest-cov
342
+ ```
343
+
344
+ ### TypeScript/JavaScript
345
+ ```bash
346
+ # Contract Testing
347
+ npm install zod
348
+
349
+ # Integration Testing
350
+ npm install @testing-library/react @testing-library/user-event
351
+
352
+ # Property-Based Testing
353
+ npm install fast-check
354
+
355
+ # E2E Testing
356
+ npm install playwright
357
+ ```
358
+
359
+ ### Dart/Flutter
360
+ ```bash
361
+ # Integration Testing
362
+ flutter pub add integration_test
363
+
364
+ # Widget Testing
365
+ flutter test
366
+
367
+ # E2E Testing (Flutter Driver)
368
+ flutter drive --target=test_driver/app.dart
369
+ ```
370
+
371
+ ## 안티패턴
372
+
373
+ ```python
374
+ # ❌ 구현 세부사항 테스트 (깨지기 쉬움)
375
+ def test_internal_cache_structure():
376
+ service = UserService()
377
+ assert service._cache == {} # 내부 구현에 의존
378
+
379
+ # ✅ 공개 API 테스트 (견고함)
380
+ def test_user_data_is_cached_after_first_call():
381
+ service = UserService()
382
+ user1 = service.get_user("123")
383
+ user2 = service.get_user("123")
384
+ assert user1 is user2 # 동작만 검증
385
+ ```
386
+
387
+ ```typescript
388
+ // ❌ 모든 함수에 Unit Test (과도함)
389
+ test('add function adds two numbers', () => {
390
+ expect(add(1, 2)).toBe(3); // 의미 없음
391
+ });
392
+
393
+ // ✅ 복잡한 로직만 테스트
394
+ test('calculate shipping cost with multiple conditions', () => {
395
+ const cost = calculateShipping({
396
+ weight: 10,
397
+ distance: 500,
398
+ isPremium: true,
399
+ isExpress: false,
400
+ });
401
+ expect(cost).toBe(45); // 복잡한 규칙 검증
402
+ });
403
+ ```
404
+
405
+ ## 테스트 커버리지 목표
406
+
407
+ ```markdown
408
+ # 현실적인 목표
409
+
410
+ - Contract Coverage: 100% (모든 API는 스키마 정의)
411
+ - Integration Coverage: 80% (주요 비즈니스 흐름)
412
+ - Unit Coverage: 선택적 (복잡한 로직만)
413
+ - E2E Coverage: 20-30% (핵심 사용자 플로우)
414
+
415
+ # ❌ 피해야 할 것
416
+ - 100% Unit Test Coverage (시간 낭비)
417
+ - 단순 CRUD에 Unit Test (Integration으로 충분)
418
+ - 모든 엣지 케이스 수동 테스트 (Property-based 사용)
419
+ ```
420
+
421
+ ## 핵심 요약
422
+
423
+ ```markdown
424
+ AI 시대 테스트 전략:
425
+
426
+ 1. ✅ Contract-First (타입/스키마 먼저)
427
+ 2. ✅ Integration Testing (실제 시나리오)
428
+ 3. ⚠️ Unit Testing (복잡한 로직만)
429
+ 4. ❌ 전통적 TDD (AI 시대엔 비효율)
430
+
431
+ 목표:
432
+ - 단일 책임 (SRP)
433
+ - 중복 제거 (DRY)
434
+ - 재사용성
435
+ - 낮은 복잡도
436
+ - 빠른 피드백
437
+ ```