@su-record/vibe 2.0.0 → 2.0.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.
- package/.claude/agents/explorer.md +48 -48
- package/.claude/agents/implementer.md +53 -53
- package/.claude/agents/searcher.md +54 -54
- package/.claude/agents/simplifier.md +119 -119
- package/.claude/agents/tester.md +49 -49
- package/.claude/commands/vibe.analyze.md +239 -239
- package/.claude/commands/vibe.continue.md +88 -88
- package/.claude/commands/vibe.diagram.md +178 -178
- package/.claude/commands/vibe.reason.md +306 -306
- package/.claude/commands/vibe.run.md +760 -760
- package/.claude/commands/vibe.spec.md +339 -339
- package/.claude/commands/vibe.tool.md +153 -153
- package/.claude/commands/vibe.ui.md +137 -137
- package/.claude/commands/vibe.verify.md +238 -238
- package/.claude/settings.json +152 -152
- package/.claude/settings.local.json +4 -57
- package/.vibe/config.json +9 -0
- package/.vibe/constitution.md +184 -184
- package/.vibe/rules/core/communication-guide.md +104 -104
- package/.vibe/rules/core/development-philosophy.md +52 -52
- package/.vibe/rules/core/quick-start.md +120 -120
- package/.vibe/rules/quality/bdd-contract-testing.md +388 -388
- package/.vibe/rules/quality/checklist.md +276 -276
- package/.vibe/rules/quality/testing-strategy.md +437 -437
- package/.vibe/rules/standards/anti-patterns.md +369 -369
- package/.vibe/rules/standards/code-structure.md +291 -291
- package/.vibe/rules/standards/complexity-metrics.md +312 -312
- package/.vibe/rules/standards/naming-conventions.md +198 -198
- package/.vibe/rules/tools/mcp-hi-ai-guide.md +665 -665
- package/.vibe/rules/tools/mcp-workflow.md +51 -51
- package/.vibe/setup.sh +31 -31
- package/CLAUDE.md +122 -122
- package/LICENSE +21 -21
- package/README.md +568 -568
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +391 -406
- package/dist/cli/index.js.map +1 -1
- package/dist/lib/MemoryManager.js +92 -92
- package/dist/lib/PythonParser.js +108 -108
- package/dist/lib/gemini-mcp.js +15 -15
- package/dist/lib/gemini-oauth.d.ts.map +1 -1
- package/dist/lib/gemini-oauth.js +41 -38
- package/dist/lib/gemini-oauth.js.map +1 -1
- package/dist/lib/gpt-mcp.js +17 -17
- package/dist/lib/gpt-oauth.d.ts.map +1 -1
- package/dist/lib/gpt-oauth.js +50 -45
- package/dist/lib/gpt-oauth.js.map +1 -1
- package/dist/tools/analytics/getUsageAnalytics.js +12 -12
- package/dist/tools/memory/createMemoryTimeline.js +10 -10
- package/dist/tools/memory/getMemoryGraph.js +12 -12
- package/dist/tools/memory/getSessionContext.js +9 -9
- package/dist/tools/memory/linkMemories.js +14 -14
- package/dist/tools/memory/listMemories.js +4 -4
- package/dist/tools/memory/recallMemory.js +4 -4
- package/dist/tools/memory/saveMemory.js +4 -4
- package/dist/tools/memory/searchMemoriesAdvanced.js +22 -22
- package/dist/tools/planning/generatePrd.js +46 -46
- package/dist/tools/prompt/enhancePromptGemini.js +160 -160
- package/dist/tools/reasoning/applyReasoningFramework.js +56 -56
- package/dist/tools/semantic/analyzeDependencyGraph.js +12 -12
- package/package.json +67 -67
- package/templates/constitution-template.md +184 -184
- package/templates/contract-backend-template.md +517 -517
- package/templates/contract-frontend-template.md +594 -594
- package/templates/feature-template.md +96 -96
- package/templates/hooks-template.json +103 -103
- package/templates/spec-template.md +199 -199
- package/dist/lib/vibe-mcp.d.ts.map +0 -1
- package/dist/lib/vibe-mcp.js.map +0 -1
|
@@ -1,388 +1,388 @@
|
|
|
1
|
-
# BDD + Contract Testing Guide
|
|
2
|
-
|
|
3
|
-
**AI 주도 개발에 최적화된 테스팅 전략**
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## 개요
|
|
8
|
-
|
|
9
|
-
BDD (Behavior-Driven Development)와 Contract Testing은 **AI 에이전트가 요구사항을 정확히 이해하고 검증 가능한 코드를 생성**하는 데 필수적입니다.
|
|
10
|
-
|
|
11
|
-
### 왜 AI 주도 개발에 유용한가?
|
|
12
|
-
|
|
13
|
-
1. **명확한 입출력 계약** → AI가 정확히 구현 가능
|
|
14
|
-
2. **자동 검증** → AI 생성 코드의 품질 즉시 확인
|
|
15
|
-
3. **회귀 방지** → AI 수정이 기존 기능을 깨뜨리지 않음
|
|
16
|
-
4. **문서화 자동화** → 테스트가 곧 실행 가능한 명세
|
|
17
|
-
|
|
18
|
-
---
|
|
19
|
-
|
|
20
|
-
## Workflow
|
|
21
|
-
|
|
22
|
-
```
|
|
23
|
-
SPEC 작성 (요구사항)
|
|
24
|
-
↓
|
|
25
|
-
Feature 파일 생성 (Gherkin)
|
|
26
|
-
↓
|
|
27
|
-
Contract 테스트 생성 (API 스키마)
|
|
28
|
-
↓
|
|
29
|
-
테스트 실행 (Red)
|
|
30
|
-
↓
|
|
31
|
-
AI 에이전트 구현
|
|
32
|
-
↓
|
|
33
|
-
테스트 실행 (Green)
|
|
34
|
-
↓
|
|
35
|
-
리팩토링
|
|
36
|
-
↓
|
|
37
|
-
테스트 재실행 (Green 유지)
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
---
|
|
41
|
-
|
|
42
|
-
## 1. BDD (Behavior-Driven Development)
|
|
43
|
-
|
|
44
|
-
### Gherkin 문법
|
|
45
|
-
|
|
46
|
-
```gherkin
|
|
47
|
-
Feature: 사용자 로그인
|
|
48
|
-
As a 사용자
|
|
49
|
-
I want to 로그인하고 싶다
|
|
50
|
-
So that 개인화된 서비스를 이용할 수 있다
|
|
51
|
-
|
|
52
|
-
Scenario: 유효한 credentials로 로그인 성공
|
|
53
|
-
Given 사용자가 "test@example.com"과 "password123"으로 등록되어 있다
|
|
54
|
-
When "test@example.com"과 "password123"으로 로그인을 시도한다
|
|
55
|
-
Then 로그인에 성공한다
|
|
56
|
-
And JWT 토큰을 받는다
|
|
57
|
-
And 홈 화면으로 리디렉션된다
|
|
58
|
-
|
|
59
|
-
Scenario: 잘못된 비밀번호로 로그인 실패
|
|
60
|
-
Given 사용자가 "test@example.com"으로 등록되어 있다
|
|
61
|
-
When "test@example.com"과 "wrong-password"로 로그인을 시도한다
|
|
62
|
-
Then 로그인에 실패한다
|
|
63
|
-
And "Invalid credentials" 에러 메시지를 받는다
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
### Step Definitions (Python)
|
|
67
|
-
|
|
68
|
-
```python
|
|
69
|
-
from pytest_bdd import scenarios, given, when, then, parsers
|
|
70
|
-
|
|
71
|
-
scenarios('features/login.feature')
|
|
72
|
-
|
|
73
|
-
@given(parsers.parse('사용자가 "{email}"과 "{password}"로 등록되어 있다'))
|
|
74
|
-
def user_exists(context, email, password):
|
|
75
|
-
context.user = create_user(email=email, password=password)
|
|
76
|
-
|
|
77
|
-
@when(parsers.parse('"{email}"과 "{password}"로 로그인을 시도한다'))
|
|
78
|
-
def attempt_login(context, email, password):
|
|
79
|
-
context.response = login(email=email, password=password)
|
|
80
|
-
|
|
81
|
-
@then('로그인에 성공한다')
|
|
82
|
-
def login_succeeds(context):
|
|
83
|
-
assert context.response.status_code == 200
|
|
84
|
-
|
|
85
|
-
@then('JWT 토큰을 받는다')
|
|
86
|
-
def receives_token(context):
|
|
87
|
-
assert 'access_token' in context.response.json()
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
---
|
|
91
|
-
|
|
92
|
-
## 2. Contract Testing
|
|
93
|
-
|
|
94
|
-
### API 계약 정의
|
|
95
|
-
|
|
96
|
-
```json
|
|
97
|
-
{
|
|
98
|
-
"request": {
|
|
99
|
-
"method": "POST",
|
|
100
|
-
"path": "/api/auth/login",
|
|
101
|
-
"body": {
|
|
102
|
-
"email": "string (email format)",
|
|
103
|
-
"password": "string (min 8 chars)"
|
|
104
|
-
}
|
|
105
|
-
},
|
|
106
|
-
"response": {
|
|
107
|
-
"status": 200,
|
|
108
|
-
"body": {
|
|
109
|
-
"access_token": "string (JWT)",
|
|
110
|
-
"refresh_token": "string (JWT)",
|
|
111
|
-
"user": {
|
|
112
|
-
"id": "uuid",
|
|
113
|
-
"email": "string",
|
|
114
|
-
"name": "string"
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
### Contract 테스트 (Python)
|
|
122
|
-
|
|
123
|
-
```python
|
|
124
|
-
import pytest
|
|
125
|
-
from jsonschema import validate
|
|
126
|
-
|
|
127
|
-
RESPONSE_SCHEMA = {
|
|
128
|
-
"type": "object",
|
|
129
|
-
"required": ["access_token", "refresh_token", "user"],
|
|
130
|
-
"properties": {
|
|
131
|
-
"access_token": {"type": "string", "pattern": "^[A-Za-z0-9-_]+\\.[A-Za-z0-9-_]+\\.[A-Za-z0-9-_]+$"},
|
|
132
|
-
"refresh_token": {"type": "string"},
|
|
133
|
-
"user": {
|
|
134
|
-
"type": "object",
|
|
135
|
-
"required": ["id", "email", "name"],
|
|
136
|
-
"properties": {
|
|
137
|
-
"id": {"type": "string", "format": "uuid"},
|
|
138
|
-
"email": {"type": "string", "format": "email"},
|
|
139
|
-
"name": {"type": "string"}
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
def test_login_response_contract():
|
|
146
|
-
"""로그인 응답이 계약을 준수하는지 검증"""
|
|
147
|
-
response = client.post("/api/auth/login", json={
|
|
148
|
-
"email": "test@example.com",
|
|
149
|
-
"password": "password123"
|
|
150
|
-
})
|
|
151
|
-
|
|
152
|
-
assert response.status_code == 200
|
|
153
|
-
|
|
154
|
-
# 응답 스키마 검증
|
|
155
|
-
validate(instance=response.json(), schema=RESPONSE_SCHEMA)
|
|
156
|
-
|
|
157
|
-
# JWT 토큰 형식 검증
|
|
158
|
-
token = response.json()["access_token"]
|
|
159
|
-
assert len(token.split('.')) == 3 # JWT는 3개 부분으로 구성
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
---
|
|
163
|
-
|
|
164
|
-
## 3. AI 에이전트 활용
|
|
165
|
-
|
|
166
|
-
### SPEC → Feature 자동 생성
|
|
167
|
-
|
|
168
|
-
AI 에이전트가 SPEC의 Acceptance Criteria를 Gherkin Scenario로 자동 변환:
|
|
169
|
-
|
|
170
|
-
**SPEC**:
|
|
171
|
-
```markdown
|
|
172
|
-
### REQ-001: 사용자 로그인
|
|
173
|
-
**WHEN** 유효한 credentials로 로그인
|
|
174
|
-
**THEN** JWT 토큰을 받는다
|
|
175
|
-
|
|
176
|
-
#### Acceptance Criteria
|
|
177
|
-
- [ ] 이메일과 비밀번호로 로그인 가능
|
|
178
|
-
- [ ] access_token과 refresh_token 반환
|
|
179
|
-
- [ ] 잘못된 credentials는 400 에러
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
**Generated Feature**:
|
|
183
|
-
```gherkin
|
|
184
|
-
Scenario: 유효한 credentials로 로그인 성공
|
|
185
|
-
Given 사용자가 등록되어 있다
|
|
186
|
-
When 유효한 이메일과 비밀번호로 로그인한다
|
|
187
|
-
Then JWT access_token을 받는다
|
|
188
|
-
And JWT refresh_token을 받는다
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
### API 스키마 → Contract 자동 생성
|
|
192
|
-
|
|
193
|
-
AI 에이전트가 SPEC의 API 계약을 Contract 테스트로 자동 변환:
|
|
194
|
-
|
|
195
|
-
**SPEC**:
|
|
196
|
-
```markdown
|
|
197
|
-
### Endpoint: 로그인
|
|
198
|
-
POST /api/auth/login
|
|
199
|
-
Request: { email, password }
|
|
200
|
-
Response: { access_token, refresh_token, user }
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
**Generated Contract Test**:
|
|
204
|
-
```python
|
|
205
|
-
def test_login_contract():
|
|
206
|
-
response = client.post("/api/auth/login", json=valid_credentials)
|
|
207
|
-
assert response.status_code == 200
|
|
208
|
-
validate(response.json(), LOGIN_RESPONSE_SCHEMA)
|
|
209
|
-
```
|
|
210
|
-
|
|
211
|
-
---
|
|
212
|
-
|
|
213
|
-
## 4. Vibe 명령어
|
|
214
|
-
|
|
215
|
-
### Feature 파일 생성
|
|
216
|
-
|
|
217
|
-
```bash
|
|
218
|
-
vibe feature "user login"
|
|
219
|
-
# → .vibe/features/user-login.feature 생성
|
|
220
|
-
```
|
|
221
|
-
|
|
222
|
-
### Contract 테스트 생성
|
|
223
|
-
|
|
224
|
-
```bash
|
|
225
|
-
vibe contract "user login"
|
|
226
|
-
# → tests/contract/test_user_login_contract.py 생성
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
### 테스트 실행
|
|
230
|
-
|
|
231
|
-
```bash
|
|
232
|
-
vibe test "user login"
|
|
233
|
-
# → BDD + Contract 테스트 실행
|
|
234
|
-
```
|
|
235
|
-
|
|
236
|
-
### 검증
|
|
237
|
-
|
|
238
|
-
```bash
|
|
239
|
-
vibe verify "user login"
|
|
240
|
-
# → SPEC Acceptance Criteria 100% 충족 확인
|
|
241
|
-
```
|
|
242
|
-
|
|
243
|
-
---
|
|
244
|
-
|
|
245
|
-
## 5. Best Practices
|
|
246
|
-
|
|
247
|
-
### ✅ DO
|
|
248
|
-
|
|
249
|
-
1. **SPEC 먼저 작성** → Feature → Contract → 구현
|
|
250
|
-
2. **Given-When-Then** 명확히 분리
|
|
251
|
-
3. **계약은 구체적으로** (타입, 형식, 제약 명시)
|
|
252
|
-
4. **독립적인 시나리오** (순서 무관하게 실행 가능)
|
|
253
|
-
5. **에러 케이스 포함** (Happy path + Sad path)
|
|
254
|
-
|
|
255
|
-
### ❌ DON'T
|
|
256
|
-
|
|
257
|
-
1. **구현 세부사항 노출 금지** (Step Definitions에만 위치)
|
|
258
|
-
2. **UI 테스트와 혼동 금지** (BDD는 비즈니스 로직)
|
|
259
|
-
3. **과도한 Background 금지** (중복 제거만)
|
|
260
|
-
4. **계약 위반 허용 금지** (스키마 변경 시 버전 업)
|
|
261
|
-
|
|
262
|
-
---
|
|
263
|
-
|
|
264
|
-
## 6. Coverage Mapping
|
|
265
|
-
|
|
266
|
-
| SPEC REQ | Feature Scenario | Contract Test | Implementation | Status |
|
|
267
|
-
|----------|------------------|---------------|----------------|--------|
|
|
268
|
-
| REQ-001 | ✅ Scenario 1, 2 | ✅ test_login_contract | ✅ POST /api/auth/login | ✅ |
|
|
269
|
-
| REQ-002 | ✅ Scenario 3 | ✅ test_refresh_contract | ⬜ POST /api/auth/refresh | ⬜ |
|
|
270
|
-
|
|
271
|
-
**Coverage**: 1 / 2 (50%)
|
|
272
|
-
|
|
273
|
-
---
|
|
274
|
-
|
|
275
|
-
## 7. CI/CD Integration
|
|
276
|
-
|
|
277
|
-
```yaml
|
|
278
|
-
# .github/workflows/test.yml
|
|
279
|
-
name: BDD + Contract Tests
|
|
280
|
-
|
|
281
|
-
on: [pull_request]
|
|
282
|
-
|
|
283
|
-
jobs:
|
|
284
|
-
test:
|
|
285
|
-
runs-on: ubuntu-latest
|
|
286
|
-
steps:
|
|
287
|
-
- uses: actions/checkout@v2
|
|
288
|
-
|
|
289
|
-
- name: Run BDD tests
|
|
290
|
-
run: pytest tests/features/ -v --gherkin-terminal-reporter
|
|
291
|
-
|
|
292
|
-
- name: Run Contract tests
|
|
293
|
-
run: pytest tests/contract/ -v
|
|
294
|
-
|
|
295
|
-
- name: Upload coverage
|
|
296
|
-
run: |
|
|
297
|
-
pytest --cov=app --cov-report=xml
|
|
298
|
-
codecov -f coverage.xml
|
|
299
|
-
```
|
|
300
|
-
|
|
301
|
-
---
|
|
302
|
-
|
|
303
|
-
## 8. Examples
|
|
304
|
-
|
|
305
|
-
### Python (FastAPI)
|
|
306
|
-
|
|
307
|
-
```bash
|
|
308
|
-
# 프로젝트 구조
|
|
309
|
-
project/
|
|
310
|
-
├── tests/
|
|
311
|
-
│ ├── features/ # Gherkin feature files
|
|
312
|
-
│ │ └── login.feature
|
|
313
|
-
│ ├── step_defs/ # Step definitions
|
|
314
|
-
│ │ └── test_login.py
|
|
315
|
-
│ └── contract/ # Contract tests
|
|
316
|
-
│ └── test_login_contract.py
|
|
317
|
-
```
|
|
318
|
-
|
|
319
|
-
### Flutter (Dart)
|
|
320
|
-
|
|
321
|
-
```bash
|
|
322
|
-
# 프로젝트 구조
|
|
323
|
-
project/
|
|
324
|
-
├── integration_test/
|
|
325
|
-
│ ├── features/ # Gherkin feature files
|
|
326
|
-
│ │ └── login.feature
|
|
327
|
-
│ └── step_definitions/ # Step definitions
|
|
328
|
-
│ └── login_test.dart
|
|
329
|
-
└── test/
|
|
330
|
-
└── contract/ # Contract tests
|
|
331
|
-
└── login_contract_test.dart
|
|
332
|
-
```
|
|
333
|
-
|
|
334
|
-
### React (TypeScript)
|
|
335
|
-
|
|
336
|
-
```bash
|
|
337
|
-
# 프로젝트 구조
|
|
338
|
-
project/
|
|
339
|
-
├── tests/
|
|
340
|
-
│ ├── features/ # Gherkin feature files
|
|
341
|
-
│ │ └── login.feature
|
|
342
|
-
│ ├── steps/ # Step definitions
|
|
343
|
-
│ │ └── login.steps.ts
|
|
344
|
-
│ └── contract/ # Contract tests
|
|
345
|
-
│ └── login.contract.test.ts
|
|
346
|
-
```
|
|
347
|
-
|
|
348
|
-
---
|
|
349
|
-
|
|
350
|
-
## 9. Tools & Frameworks
|
|
351
|
-
|
|
352
|
-
### BDD
|
|
353
|
-
|
|
354
|
-
| Language | Framework |
|
|
355
|
-
|----------|-----------|
|
|
356
|
-
| Python | pytest-bdd, behave |
|
|
357
|
-
| JavaScript | Cucumber.js, Jest-Cucumber |
|
|
358
|
-
| TypeScript | Cucumber.js, Playwright |
|
|
359
|
-
| Dart | flutter_gherkin |
|
|
360
|
-
| Java | Cucumber-JVM |
|
|
361
|
-
| Ruby | Cucumber |
|
|
362
|
-
|
|
363
|
-
### Contract Testing
|
|
364
|
-
|
|
365
|
-
| Type | Framework |
|
|
366
|
-
|------|-----------|
|
|
367
|
-
| Consumer-Driven | Pact, Spring Cloud Contract |
|
|
368
|
-
| Provider | Postman, Dredd |
|
|
369
|
-
| Schema Validation | JSON Schema, Zod, Ajv |
|
|
370
|
-
| Mock Server | MSW, WireMock, http-mock-adapter |
|
|
371
|
-
|
|
372
|
-
---
|
|
373
|
-
|
|
374
|
-
## Summary
|
|
375
|
-
|
|
376
|
-
BDD + Contract Testing은 **AI 에이전트가 SPEC을 정확히 구현하고 자동 검증**할 수 있게 합니다:
|
|
377
|
-
|
|
378
|
-
1. **명확한 요구사항** → Gherkin으로 비즈니스 언어 표현
|
|
379
|
-
2. **계약 기반 개발** → API 스키마로 Frontend/Backend 독립 개발
|
|
380
|
-
3. **자동화된 검증** → AI 생성 코드 품질 즉시 확인
|
|
381
|
-
4. **회귀 방지** → 기존 기능 보호
|
|
382
|
-
|
|
383
|
-
**Vibe에서 사용**:
|
|
384
|
-
```bash
|
|
385
|
-
vibe spec "feature" → vibe feature "feature" → vibe contract "feature" → vibe run
|
|
386
|
-
```
|
|
387
|
-
|
|
388
|
-
**Test-First → AI 구현 → Verify → Done** 🎉
|
|
1
|
+
# BDD + Contract Testing Guide
|
|
2
|
+
|
|
3
|
+
**AI 주도 개발에 최적화된 테스팅 전략**
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 개요
|
|
8
|
+
|
|
9
|
+
BDD (Behavior-Driven Development)와 Contract Testing은 **AI 에이전트가 요구사항을 정확히 이해하고 검증 가능한 코드를 생성**하는 데 필수적입니다.
|
|
10
|
+
|
|
11
|
+
### 왜 AI 주도 개발에 유용한가?
|
|
12
|
+
|
|
13
|
+
1. **명확한 입출력 계약** → AI가 정확히 구현 가능
|
|
14
|
+
2. **자동 검증** → AI 생성 코드의 품질 즉시 확인
|
|
15
|
+
3. **회귀 방지** → AI 수정이 기존 기능을 깨뜨리지 않음
|
|
16
|
+
4. **문서화 자동화** → 테스트가 곧 실행 가능한 명세
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Workflow
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
SPEC 작성 (요구사항)
|
|
24
|
+
↓
|
|
25
|
+
Feature 파일 생성 (Gherkin)
|
|
26
|
+
↓
|
|
27
|
+
Contract 테스트 생성 (API 스키마)
|
|
28
|
+
↓
|
|
29
|
+
테스트 실행 (Red)
|
|
30
|
+
↓
|
|
31
|
+
AI 에이전트 구현
|
|
32
|
+
↓
|
|
33
|
+
테스트 실행 (Green)
|
|
34
|
+
↓
|
|
35
|
+
리팩토링
|
|
36
|
+
↓
|
|
37
|
+
테스트 재실행 (Green 유지)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## 1. BDD (Behavior-Driven Development)
|
|
43
|
+
|
|
44
|
+
### Gherkin 문법
|
|
45
|
+
|
|
46
|
+
```gherkin
|
|
47
|
+
Feature: 사용자 로그인
|
|
48
|
+
As a 사용자
|
|
49
|
+
I want to 로그인하고 싶다
|
|
50
|
+
So that 개인화된 서비스를 이용할 수 있다
|
|
51
|
+
|
|
52
|
+
Scenario: 유효한 credentials로 로그인 성공
|
|
53
|
+
Given 사용자가 "test@example.com"과 "password123"으로 등록되어 있다
|
|
54
|
+
When "test@example.com"과 "password123"으로 로그인을 시도한다
|
|
55
|
+
Then 로그인에 성공한다
|
|
56
|
+
And JWT 토큰을 받는다
|
|
57
|
+
And 홈 화면으로 리디렉션된다
|
|
58
|
+
|
|
59
|
+
Scenario: 잘못된 비밀번호로 로그인 실패
|
|
60
|
+
Given 사용자가 "test@example.com"으로 등록되어 있다
|
|
61
|
+
When "test@example.com"과 "wrong-password"로 로그인을 시도한다
|
|
62
|
+
Then 로그인에 실패한다
|
|
63
|
+
And "Invalid credentials" 에러 메시지를 받는다
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Step Definitions (Python)
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
from pytest_bdd import scenarios, given, when, then, parsers
|
|
70
|
+
|
|
71
|
+
scenarios('features/login.feature')
|
|
72
|
+
|
|
73
|
+
@given(parsers.parse('사용자가 "{email}"과 "{password}"로 등록되어 있다'))
|
|
74
|
+
def user_exists(context, email, password):
|
|
75
|
+
context.user = create_user(email=email, password=password)
|
|
76
|
+
|
|
77
|
+
@when(parsers.parse('"{email}"과 "{password}"로 로그인을 시도한다'))
|
|
78
|
+
def attempt_login(context, email, password):
|
|
79
|
+
context.response = login(email=email, password=password)
|
|
80
|
+
|
|
81
|
+
@then('로그인에 성공한다')
|
|
82
|
+
def login_succeeds(context):
|
|
83
|
+
assert context.response.status_code == 200
|
|
84
|
+
|
|
85
|
+
@then('JWT 토큰을 받는다')
|
|
86
|
+
def receives_token(context):
|
|
87
|
+
assert 'access_token' in context.response.json()
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## 2. Contract Testing
|
|
93
|
+
|
|
94
|
+
### API 계약 정의
|
|
95
|
+
|
|
96
|
+
```json
|
|
97
|
+
{
|
|
98
|
+
"request": {
|
|
99
|
+
"method": "POST",
|
|
100
|
+
"path": "/api/auth/login",
|
|
101
|
+
"body": {
|
|
102
|
+
"email": "string (email format)",
|
|
103
|
+
"password": "string (min 8 chars)"
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
"response": {
|
|
107
|
+
"status": 200,
|
|
108
|
+
"body": {
|
|
109
|
+
"access_token": "string (JWT)",
|
|
110
|
+
"refresh_token": "string (JWT)",
|
|
111
|
+
"user": {
|
|
112
|
+
"id": "uuid",
|
|
113
|
+
"email": "string",
|
|
114
|
+
"name": "string"
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Contract 테스트 (Python)
|
|
122
|
+
|
|
123
|
+
```python
|
|
124
|
+
import pytest
|
|
125
|
+
from jsonschema import validate
|
|
126
|
+
|
|
127
|
+
RESPONSE_SCHEMA = {
|
|
128
|
+
"type": "object",
|
|
129
|
+
"required": ["access_token", "refresh_token", "user"],
|
|
130
|
+
"properties": {
|
|
131
|
+
"access_token": {"type": "string", "pattern": "^[A-Za-z0-9-_]+\\.[A-Za-z0-9-_]+\\.[A-Za-z0-9-_]+$"},
|
|
132
|
+
"refresh_token": {"type": "string"},
|
|
133
|
+
"user": {
|
|
134
|
+
"type": "object",
|
|
135
|
+
"required": ["id", "email", "name"],
|
|
136
|
+
"properties": {
|
|
137
|
+
"id": {"type": "string", "format": "uuid"},
|
|
138
|
+
"email": {"type": "string", "format": "email"},
|
|
139
|
+
"name": {"type": "string"}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
def test_login_response_contract():
|
|
146
|
+
"""로그인 응답이 계약을 준수하는지 검증"""
|
|
147
|
+
response = client.post("/api/auth/login", json={
|
|
148
|
+
"email": "test@example.com",
|
|
149
|
+
"password": "password123"
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
assert response.status_code == 200
|
|
153
|
+
|
|
154
|
+
# 응답 스키마 검증
|
|
155
|
+
validate(instance=response.json(), schema=RESPONSE_SCHEMA)
|
|
156
|
+
|
|
157
|
+
# JWT 토큰 형식 검증
|
|
158
|
+
token = response.json()["access_token"]
|
|
159
|
+
assert len(token.split('.')) == 3 # JWT는 3개 부분으로 구성
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## 3. AI 에이전트 활용
|
|
165
|
+
|
|
166
|
+
### SPEC → Feature 자동 생성
|
|
167
|
+
|
|
168
|
+
AI 에이전트가 SPEC의 Acceptance Criteria를 Gherkin Scenario로 자동 변환:
|
|
169
|
+
|
|
170
|
+
**SPEC**:
|
|
171
|
+
```markdown
|
|
172
|
+
### REQ-001: 사용자 로그인
|
|
173
|
+
**WHEN** 유효한 credentials로 로그인
|
|
174
|
+
**THEN** JWT 토큰을 받는다
|
|
175
|
+
|
|
176
|
+
#### Acceptance Criteria
|
|
177
|
+
- [ ] 이메일과 비밀번호로 로그인 가능
|
|
178
|
+
- [ ] access_token과 refresh_token 반환
|
|
179
|
+
- [ ] 잘못된 credentials는 400 에러
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
**Generated Feature**:
|
|
183
|
+
```gherkin
|
|
184
|
+
Scenario: 유효한 credentials로 로그인 성공
|
|
185
|
+
Given 사용자가 등록되어 있다
|
|
186
|
+
When 유효한 이메일과 비밀번호로 로그인한다
|
|
187
|
+
Then JWT access_token을 받는다
|
|
188
|
+
And JWT refresh_token을 받는다
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### API 스키마 → Contract 자동 생성
|
|
192
|
+
|
|
193
|
+
AI 에이전트가 SPEC의 API 계약을 Contract 테스트로 자동 변환:
|
|
194
|
+
|
|
195
|
+
**SPEC**:
|
|
196
|
+
```markdown
|
|
197
|
+
### Endpoint: 로그인
|
|
198
|
+
POST /api/auth/login
|
|
199
|
+
Request: { email, password }
|
|
200
|
+
Response: { access_token, refresh_token, user }
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
**Generated Contract Test**:
|
|
204
|
+
```python
|
|
205
|
+
def test_login_contract():
|
|
206
|
+
response = client.post("/api/auth/login", json=valid_credentials)
|
|
207
|
+
assert response.status_code == 200
|
|
208
|
+
validate(response.json(), LOGIN_RESPONSE_SCHEMA)
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## 4. Vibe 명령어
|
|
214
|
+
|
|
215
|
+
### Feature 파일 생성
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
vibe feature "user login"
|
|
219
|
+
# → .vibe/features/user-login.feature 생성
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Contract 테스트 생성
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
vibe contract "user login"
|
|
226
|
+
# → tests/contract/test_user_login_contract.py 생성
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### 테스트 실행
|
|
230
|
+
|
|
231
|
+
```bash
|
|
232
|
+
vibe test "user login"
|
|
233
|
+
# → BDD + Contract 테스트 실행
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### 검증
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
vibe verify "user login"
|
|
240
|
+
# → SPEC Acceptance Criteria 100% 충족 확인
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
## 5. Best Practices
|
|
246
|
+
|
|
247
|
+
### ✅ DO
|
|
248
|
+
|
|
249
|
+
1. **SPEC 먼저 작성** → Feature → Contract → 구현
|
|
250
|
+
2. **Given-When-Then** 명확히 분리
|
|
251
|
+
3. **계약은 구체적으로** (타입, 형식, 제약 명시)
|
|
252
|
+
4. **독립적인 시나리오** (순서 무관하게 실행 가능)
|
|
253
|
+
5. **에러 케이스 포함** (Happy path + Sad path)
|
|
254
|
+
|
|
255
|
+
### ❌ DON'T
|
|
256
|
+
|
|
257
|
+
1. **구현 세부사항 노출 금지** (Step Definitions에만 위치)
|
|
258
|
+
2. **UI 테스트와 혼동 금지** (BDD는 비즈니스 로직)
|
|
259
|
+
3. **과도한 Background 금지** (중복 제거만)
|
|
260
|
+
4. **계약 위반 허용 금지** (스키마 변경 시 버전 업)
|
|
261
|
+
|
|
262
|
+
---
|
|
263
|
+
|
|
264
|
+
## 6. Coverage Mapping
|
|
265
|
+
|
|
266
|
+
| SPEC REQ | Feature Scenario | Contract Test | Implementation | Status |
|
|
267
|
+
|----------|------------------|---------------|----------------|--------|
|
|
268
|
+
| REQ-001 | ✅ Scenario 1, 2 | ✅ test_login_contract | ✅ POST /api/auth/login | ✅ |
|
|
269
|
+
| REQ-002 | ✅ Scenario 3 | ✅ test_refresh_contract | ⬜ POST /api/auth/refresh | ⬜ |
|
|
270
|
+
|
|
271
|
+
**Coverage**: 1 / 2 (50%)
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## 7. CI/CD Integration
|
|
276
|
+
|
|
277
|
+
```yaml
|
|
278
|
+
# .github/workflows/test.yml
|
|
279
|
+
name: BDD + Contract Tests
|
|
280
|
+
|
|
281
|
+
on: [pull_request]
|
|
282
|
+
|
|
283
|
+
jobs:
|
|
284
|
+
test:
|
|
285
|
+
runs-on: ubuntu-latest
|
|
286
|
+
steps:
|
|
287
|
+
- uses: actions/checkout@v2
|
|
288
|
+
|
|
289
|
+
- name: Run BDD tests
|
|
290
|
+
run: pytest tests/features/ -v --gherkin-terminal-reporter
|
|
291
|
+
|
|
292
|
+
- name: Run Contract tests
|
|
293
|
+
run: pytest tests/contract/ -v
|
|
294
|
+
|
|
295
|
+
- name: Upload coverage
|
|
296
|
+
run: |
|
|
297
|
+
pytest --cov=app --cov-report=xml
|
|
298
|
+
codecov -f coverage.xml
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
## 8. Examples
|
|
304
|
+
|
|
305
|
+
### Python (FastAPI)
|
|
306
|
+
|
|
307
|
+
```bash
|
|
308
|
+
# 프로젝트 구조
|
|
309
|
+
project/
|
|
310
|
+
├── tests/
|
|
311
|
+
│ ├── features/ # Gherkin feature files
|
|
312
|
+
│ │ └── login.feature
|
|
313
|
+
│ ├── step_defs/ # Step definitions
|
|
314
|
+
│ │ └── test_login.py
|
|
315
|
+
│ └── contract/ # Contract tests
|
|
316
|
+
│ └── test_login_contract.py
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
### Flutter (Dart)
|
|
320
|
+
|
|
321
|
+
```bash
|
|
322
|
+
# 프로젝트 구조
|
|
323
|
+
project/
|
|
324
|
+
├── integration_test/
|
|
325
|
+
│ ├── features/ # Gherkin feature files
|
|
326
|
+
│ │ └── login.feature
|
|
327
|
+
│ └── step_definitions/ # Step definitions
|
|
328
|
+
│ └── login_test.dart
|
|
329
|
+
└── test/
|
|
330
|
+
└── contract/ # Contract tests
|
|
331
|
+
└── login_contract_test.dart
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
### React (TypeScript)
|
|
335
|
+
|
|
336
|
+
```bash
|
|
337
|
+
# 프로젝트 구조
|
|
338
|
+
project/
|
|
339
|
+
├── tests/
|
|
340
|
+
│ ├── features/ # Gherkin feature files
|
|
341
|
+
│ │ └── login.feature
|
|
342
|
+
│ ├── steps/ # Step definitions
|
|
343
|
+
│ │ └── login.steps.ts
|
|
344
|
+
│ └── contract/ # Contract tests
|
|
345
|
+
│ └── login.contract.test.ts
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
---
|
|
349
|
+
|
|
350
|
+
## 9. Tools & Frameworks
|
|
351
|
+
|
|
352
|
+
### BDD
|
|
353
|
+
|
|
354
|
+
| Language | Framework |
|
|
355
|
+
|----------|-----------|
|
|
356
|
+
| Python | pytest-bdd, behave |
|
|
357
|
+
| JavaScript | Cucumber.js, Jest-Cucumber |
|
|
358
|
+
| TypeScript | Cucumber.js, Playwright |
|
|
359
|
+
| Dart | flutter_gherkin |
|
|
360
|
+
| Java | Cucumber-JVM |
|
|
361
|
+
| Ruby | Cucumber |
|
|
362
|
+
|
|
363
|
+
### Contract Testing
|
|
364
|
+
|
|
365
|
+
| Type | Framework |
|
|
366
|
+
|------|-----------|
|
|
367
|
+
| Consumer-Driven | Pact, Spring Cloud Contract |
|
|
368
|
+
| Provider | Postman, Dredd |
|
|
369
|
+
| Schema Validation | JSON Schema, Zod, Ajv |
|
|
370
|
+
| Mock Server | MSW, WireMock, http-mock-adapter |
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
374
|
+
## Summary
|
|
375
|
+
|
|
376
|
+
BDD + Contract Testing은 **AI 에이전트가 SPEC을 정확히 구현하고 자동 검증**할 수 있게 합니다:
|
|
377
|
+
|
|
378
|
+
1. **명확한 요구사항** → Gherkin으로 비즈니스 언어 표현
|
|
379
|
+
2. **계약 기반 개발** → API 스키마로 Frontend/Backend 독립 개발
|
|
380
|
+
3. **자동화된 검증** → AI 생성 코드 품질 즉시 확인
|
|
381
|
+
4. **회귀 방지** → 기존 기능 보호
|
|
382
|
+
|
|
383
|
+
**Vibe에서 사용**:
|
|
384
|
+
```bash
|
|
385
|
+
vibe spec "feature" → vibe feature "feature" → vibe contract "feature" → vibe run
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
**Test-First → AI 구현 → Verify → Done** 🎉
|