| name | tdd-workflow |
| description | RED → GREEN → REFACTOR 사이클을 절차로 강제하는 스킬. snapmany의 어떤 코드든 새로 작성하거나 수정할 때 반드시 이 절차를 따른다. 컴포넌트, route handler, lib wrapper, config — 예외 없음. "테스트 작성", "TDD", "구현 추가", "기능 추가", "리팩터링", "버그 픽스" 같은 요청이 들어오면 무조건 이 스킬을 트리거한다. |
TDD Workflow
코드를 한 줄이라도 새로 쓰거나 고치기 전에 이 절차를 따른다. 이유: 테스트가 먼저 있으면 구현이 검증 가능한 모양으로 수렴한다. 테스트가 나중이면 "통과하도록" 사후 조정되어 본래 의도가 흐려진다.
절차
1. RED — 실패하는 테스트를 먼저 쓴다
- 단위 테스트 파일을 만들거나 기존 테스트에 케이스를 추가한다 (Vitest 기준).
- 아직 존재하지 않는 함수/컴포넌트를 import해서 호출하거나 렌더한다.
npm run test를 돌려 테스트가 실패하는지 확인한다. 실패 메시지가 "module not found" 같은 import 에러여도 OK — "기능이 없어서 실패"이면 RED 통과.
- 통과하면 안 된다. 통과한다면 테스트가 무엇도 검증하지 않는다는 뜻이다.
2. GREEN — 최소 구현으로 테스트를 통과시킨다
- 가장 단순한 구현으로 테스트를 통과시킨다. 일반화는 다음 단계에서.
- 다른 곳을 만지지 않는다. 테스트가 요구하는 인터페이스와 동작만 구현.
npm run test로 해당 테스트가 통과하는지 확인.
3. REFACTOR — 풀 파이프라인 게이트
GREEN 직후 반드시 아래 4개 명령을 순서대로 모두 통과시킨다. 하나라도 실패하면 다음 단계로 가지 않는다.
npm run typecheck
npm run lint
npm run test
npm run build
이 게이트는 양보 불가다. "내 코드는 동작하니까 typecheck 에러는 무시"는 금지. typecheck 에러는 빌드 실패로 이어지고, 빌드 실패는 Cloudflare 배포 실패로 이어진다.
모듈 완성의 정의
QA 에이전트가 모듈을 "완성됐다"고 인정하는 기준:
이 셋 중 하나라도 빠지면 모듈은 미완성이다.
TDD가 어려운 경우 처리법
| 상황 | 대처 |
|---|
| UI 시각 디자인 | Playwright로 스냅샷/시각 회귀 대신 동작 단위 테스트 — 버튼 disabled, 클릭 시 dispatch, 폼 검증 메시지 등 |
| 외부 API 호출 (Replicate) | client wrapper를 mock으로 주입, 실제 호출은 별도 통합 테스트에서만 |
| 환경변수 의존 | vi.stubEnv로 테스트 격리 |
| Firebase Remote Config | RC 모듈 자체를 mock, default fallback 분기 테스트는 RC를 throw하도록 |
일반화 원칙
테스트 케이스를 좁게 (특정 입력값에만 통과하도록) 작성하면 구현이 하드코딩으로 통과해 버린다. 테스트는 속성 기반으로 작성한다:
- "10MB를 넘으면 에러" (정확히 10MB+1 바이트가 아니라)
- "jpg/png/webp가 아니면 에러" (gif 케이스 하나만이 아니라 매트릭스)
- "styleIds가 알려진 집합에 없으면 에러" (특정 ID 하나가 아니라)
안티패턴
- 구현을 다 짠 후 통과하는 테스트만 작성 (이미 결론이 정해져 있어 검증력 없음)
- 단언이 없는 테스트 (
expect 호출 없이 render만)
- 모든 케이스에 mock만 두고 실제 로직을 호출하지 않는 테스트
console.log로 통과 확인 (단언으로 표현 가능하면 단언으로)