| name | tdd-practices |
| description | RED-GREEN-REFACTOR 사이클 기반 테스트 주도 개발(TDD) 가이드. 새 기능 구현, 버그 수정, 리팩토링 시 실패하는 테스트를 먼저 작성하고 최소 구현으로 통과시킵니다. AI 안티패턴(테스트 삭제, 과도한 구현)을 자동 감지하고 경고합니다. |
TDD Practices
Phase 1: TDD 세션 시작
새 기능이나 수정 작업 시작 시:
요구사항 파악
- 사용자가 요청한 기능을 명확히 이해
- 모호한 부분은 사용자에게 질문
테스트 리스트 작성
- 구현에 필요한 모든 테스트 케이스 나열
- 단순한 것부터 복잡한 순서로 정렬
- 사용자에게 목록 보여주고 확인받기
- 예: "다음 테스트들을 순서대로 진행하겠습니다: 1) ..., 2) ..., 3) ..."
Baseline 확인
- 기존 테스트 전체 실행
- 모두 통과하는지 확인
- 실패하는 테스트가 있다면 먼저 수정
Phase 2 (RED)로 진행
Phase 2: RED - 실패하는 테스트 작성
테스트 리스트의 각 항목에 대해:
작고 구체적인 테스트 하나 작성
- 한 번에 하나의 동작만 검증
- 테스트 이름은 의도를 명확히 표현
- AAA 패턴 권장 (Arrange-Act-Assert)
- ✨ 테스트 작성 = 설계 활동: 테스트하기 쉬운 인터페이스를 설계
- 부작용 최소화
- 의존성 명시적으로 표현
- 입력과 출력이 명확한 구조
테스트 실행
- 작성한 테스트만 먼저 실행
- 실패 메시지와 이유 확인
올바른 이유로 실패하는지 검증
- ⚠️ 테스트가 즉시 통과: 이미 구현이 존재함, 다른 테스트 선택
- ⚠️ 테스트가 실행 안 됨: 문법 오류, 진행 전 수정 필요
- ✅ 예상한 이유로 실패: 정상, 다음 단계 진행
실패 출력을 사용자에게 보여주기
- 어떤 테스트가 실패했는지
- 왜 실패했는지 (예상값 vs 실제값)
Phase 3 (GREEN)으로 진행
Phase 3: GREEN - 최소 구현
테스트를 통과시키기 위해:
가장 단순한 코드 작성
- 하드코딩 허용 (Fake It 전략)
- 정말 단순하고 명백한 경우에만 일반화된 구현
- 요청하지 않은 기능 절대 추가 금지 ⚠️
허용되는 전략
- Fake It: 하드코딩된 값 반환 (나중에 삼각측량으로 일반화)
- Obvious Implementation: 구현이 정말 명백한 경우
- Triangulation: 여러 테스트로 일반화 유도 → ✨ 여러 테스트를 통과시키다 보면 자연스럽게 범용적 설계가 도출됨
테스트 실행 → 통과 확인
- 방금 작성한 테스트 실행
- 통과하는지 확인
전체 테스트 실행 → 회귀 없음 확인
- 기존 테스트들이 여전히 통과하는지 확인
- 회귀가 발생했다면 즉시 수정
통과 출력을 사용자에게 보여주기
Phase 4 (REFACTOR)로 진행
GREEN 단계의 AI Red Flags 🚨
다음 징후 발견 시 즉시 중단하고 사용자에게 보고:
- 🚨 현재 테스트에 없는 기능 추가
- 예: 로그인 테스트인데 관리자 체크, 로깅 추가
- 🚨 하드코딩으로 충분한데 반복문/조건문 사용
- 첫 테스트에서는 하드코딩이 정상
- 🚨 테스트 수정/삭제로 통과 시도
- 테스트가 틀렸다면 사용자 확인 필요
- 🚨 조기 최적화
- 캐싱, 성능 최적화는 요청받지 않았다면 금지
Phase 4: REFACTOR - 동작 변경 없이 개선
핵심 원칙: 구조 변경과 기능 변경을 절대 섞지 말 것
테스트가 모두 통과한 후:
코드 냄새 식별
- 중복 코드 (Copy & Paste)
- 불명확한 변수/함수 이름
- 긴 함수
- 복잡한 조건문
- ✨ 테스트하기 어려운 코드 (설계 재고 신호):
- 부작용이 많거나 의존성이 강하게 결합된 코드
- 단일 책임 원칙(SRP) 위반
- 테스트 작성이 어렵다면 → 함수 쪼개기, 의존성 주입 고려
한 번에 하나의 리팩토링만 적용
- Extract Method (메서드 추출)
- Rename (이름 변경)
- Remove Duplication (중복 제거)
- Inline (불필요한 간접 참조 제거)
각 리팩토링 후 즉시 테스트 실행
- 모든 테스트가 여전히 통과하는지 확인
- 실패 시 → 리팩토링 되돌리고 다른 방법 시도
리팩토링이 끝나면 커밋
- 깨끗한 상태로 유지
REFACTOR 단계에서 절대 금지 ❌
- ❌ 새 기능 추가: 기능은 다음 RED-GREEN 사이클에서
- ❌ 테스트 기댓값 변경: 동작 변경의 증거
- ❌ 리팩토링과 기능 변경 혼합: 별도 커밋으로 분리
- ❌ 테스트 통과를 위한 코드 수정: REFACTOR는 이미 통과한 상태
REFACTOR 중 테스트 실패 시
테스트가 실패했다면:
- 리팩토링이 아니라 동작 변경을 했다는 증거
- 즉시 되돌리기
- 더 작은 단위로 리팩토링 시도
- Phase 5로 진행
Phase 5: 반복 또는 완료
리팩토링 후:
테스트 리스트로 돌아가기
- 완료한 테스트 체크
- 남은 테스트 확인
다음 단계 결정
- 남은 테스트 있음 → Phase 2 (RED)로 돌아가기
- 모든 테스트 완료 → 완료 조건 확인
완료 조건 확인
- ✅ 모든 테스트 통과
- ✅ 중복 코드 제거됨
- ✅ 의도가 명확함 (이름, 구조)
- ✅ 예상한 모든 케이스 커버
필요 시 문서 업데이트
- 새 기능에 대한 설명
- API 변경사항 기록
예시
예시 1: Fake It에서 일반화
첫 번째 테스트 + 구현 (Fake It):
def test_add():
assert add(2, 3) == 5
def add(a, b):
return 5 # 하드코딩 OK
두 번째 테스트 → 일반화 강제:
def test_add_different():
assert add(1, 1) == 2 # 실패: assert 5 == 2
# 일반화된 구현
def add(a, b):
return a + b
전체 테스트 실행 → 모두 통과 ✓
예시 2: AI Red Flag 감지
테스트:
def test_login():
assert login("user", "pass") == True
⚠️ AI가 생성한 코드 (나쁨):
def login(username, password):
check_admin_privileges(username) # 🚨 요청 안 함
log_access(username) # 🚨 요청 안 함
send_notification(username) # 🚨 요청 안 함
return True
조치: 즉시 중단하고 사용자에게 보고
⚠️ AI Red Flag 감지:
현재 테스트는 True 반환만 검증합니다.
AI가 요청하지 않은 기능들을 추가하려 합니다:
- 관리자 권한 체크
- 접근 로깅
- 알림 전송
GREEN 단계에서는 테스트 통과에 필요한 최소 코드만 작성해야 합니다.
진행 방법을 선택해주세요:
1. Fake It으로 단순히 True 반환 (권장)
2. 추가 기능을 테스트 리스트에 추가하고 순차 진행
✅ 올바른 코드:
def login(username, password):
return True # Fake It OK
상세 참조는 REFERENCE.md를 확인하세요.