# 02 · 의미 있는 RED vs 의미 없는 RED **목적**: 'RED'라는 이름 아래 흔히 섞여 있는 것들을 "행위를 정말 명세·검증하는가"라는 단일 기준으로 **의미 있음/의미 없음**으로 분리한다. 판정 원칙 한 줄: *"이 테스트가, 구현을 고치지 않았는데 통과할 수 있는가? 통과해도 아무것도 증명하지 않는가? 그렇다면 의미 없는 RED다."* --- ## 판정 축 (5 기준) | # | 축 | 의미 있는 RED 는… | 의미 없는 RED 는… | |---|---|---|---| | 1 | **행위(behavior)** | 공개 인터페이스/관찰 가능한 결과 하나를 명세 | 내부 구현·프라이빗 메서드·호출 순서·데이터 구조 세부 | | 2 | **단정(assertion)** | 실제 결함을 잡을 수 있는 강한 단정 | 단정 없음 / 상수 단정 / 커버리지만 채움 | | 3 | **실패 이유** | "행위 부재 **또는 결함 재현**" 예상된 이유로 실패 | 컴파일·셋업·문법·무관한 이유로 실패(그래도 빨강) | | 4 | **결정성** | 결정적·저비용·재현 가능, 시간/랜덤/네트워크 제어 | 비결정적, flaky, 외부 인프라 의존, 목으로 전부 인공화 | | 5 | **의도(설계)** | 테스트를 쓰며 인터페이스 설계를 의도적으로 결정 | 테스트 목록 없이 즉흥, 구현 세부를 그대로 돌려보기 | > 한 축이라도 "의미 없음"이면 그 RED는 빈 껍데기다. 특히 **(2) 단정**과 **(3) 실패 이유**가 핵심. --- ## 의미 있는 RED (KEEP) — 12가지 **패턴 카탈로그** > **레드팀 정정**: 아래 12가지는 상호배타적인 '유형'이 아니라, **5축(판정 축)을 충족하는 사례의 패턴 카탈로그**다. > 하나의 좋은 테스트는 여러 패턴을 동시에 충족한다(예: #1+#8+#10). "12 중 하나"라기보다 **5축을 모두 충족해야** 의미 있으며 > 12가지는 그 판정을 돕는 예시다. 특성화(#12)·회귀(#3)는 "행위 부재로 실패" 정의의 **명시적 예외**(레거시/결함)다. | 패턴 | 설명 | 근거 | |---|---|---| | 1. **행위 우선 RED** | 한 가지 비즈니스 규칙/관찰 결과를 먼저 명세, 그 행위 없음으로 실패 | Fowler, Canon TDD | | 2. **경계·엣지 RED** | 경계값(50원, 49.99원), 빈 입력, null, malformed, 오류 경로, 상태전이 | Microsoft, spec-driven | | 3. **회귀 RED** | 결함을 재현(실패 이유=결함 재현) — fix 전에 실패 확인, 정의 예외 | Fowler, Alderson | | 4. **인터페이스 설계 RED** | 테스트 작성 시점에 API/시그니처를 의도적으로 결정 | Beck Design-in-TDD | | 5. **삼각측량 RED** | 예제를 하나씩 추가하며 일반화를 강제 (Fake→Triangulate→Obvious) | TDD By Example | | 6. **결함-검출 잠재력 RED** | "구현이 미묘하게 틀려도 통과할까?"에 NO가 나오는 테스트 | Microsoft, 뮤테이션 | | 7. **외부 강제 수용 RED (AI)** | 인간이 쓴 보호 수용 테스트로 에이전트의 완료를 게이트 | 2026 TDD-Agent, TDAD, TDFlow | | 8. **블랙박스 RED** | 결과·상태변화·예외·외부 상호작용만 단정, 세부 구현 비의존 → 리팩터에 생존 | fowler_test_pyramid | | 9. **Traceable RED** | 요구→수용 시나리오→테스트 ID→파일 추적 가능 | SDD traceability | | 10. **설명력 있는 RED** | 이름이 `Withdraw_BalanceInsufficient_Throws` — 실패 시 무엇이 깨졌는지 즉시 | Microsoft, AAA | | 11. **독립 검증 RED (AI)** | 구현 에이전트와 분리된 검증자/모델·신선 컨텍스트가 작성 | 2026 권장 루프 | | 12. **특성화 (레거시 전처리)** | 기존 동작을 승인/캡처해 리팩터 안전망으로 — **RED 정의의 예외**: 즉시 통과(행위 없음이 아님) | Characterization/Approval | --- ## 의미 없는 RED (DELETE) — 10가지 | 유형 | 증상 | 왜 나쁜가 | 근거 | |---|---|---|---| | 1. **가짜 RED (fake)** | `expect(true).toBe(true)`, 단정 없음 | 커버리지만 높이고 결함 0 검출 | survey, Microsoft | | 2. **사소한 RED (trivial)** | getter·언어기능·프레임워크 반복 테스트 | 결함-검출 가치 없음 | survey | | 3. **구현-세부 RED** | 프라이빗 메서드·내부 호출순서·데이터 구조 단정 | 리팩터 때마다 깨져 재작성 → 리팩터를 막음 | fowler_test_pyramid | | 4. **인공 시스템 RED** | 전부 목/스텁으로 인공화, 실제 통합 경계 미검증 | 실제 결함을 놓침, DHH의 'test-induced damage' | Is TDD Dead | | 5. **복붙 기대값 RED** | 계산 결과를 그대로 기대값에 복붙 | 이중검증 파괴, 자신의 버그를 '정답'으로 고정 | Beck Canon TDD | | 6. **커버리지-채움 RED** | 단정 삭제/축소로 위장 초록, %만 올리기 | 은탄환이 아닌 커버리지 | Beck, Google | | 7. **의례적(all-at-once) RED** | (단위 계층) 테스트를 전부 먼저 쓰고 구현 — **수용·보호 계층의 사전 작성은 예외** | 첫 테스트가 후속 사양을 무효화하면 대량 낭비 | Beck Canon TDD | | 8. **비결정 RED** | 시간·랜덤·네트워크·DB·셰어드 상태 의존 | flaky → 신뢰 상실, zero-tolerance 대상 | Azure WAF, Microsoft | | 9. **비대(broad) RED** | 수많은 시나리오를 전 계층에 중복 반복 | 유지보수 폭증, 신호 희석 | Google "No more E2E" | | 10. **에이전트 약화 RED** | 테스트 삭제·스킵·비활성·광범위 목 대체·참조 없는 과잉 구현 | 독립 검증 붕괴, 에이전트가 지름길 (주의: #10은 '삭제 대상 테스트'가 아니라 **금지 프로세스 행동** — 판정 워크플로로는 잡히지 않음) | Alderson, Emily Bache/Probity | --- ## 판정 워크플로 (이 테스트를 유지/삭제할까?) ``` 1. 이름이 행위를 명세하는가? (아니오 → 수정 또는 삭제) 2. 단정이 결함을 잡을 수 있는가? (아니오 → 뮤테이션으로 확인 후 삭제) 3. 깨졌을 때 이유가 명확한가? (아니오 → 세부 구현 의존 의심) 4. 구현을 고치지 않고 통과할 수 있는가? (예 → 가짜/사소, 삭제) 5. 구현 세부(프라이빗/호출순서)를 검증? (예 → 블랙박스로 재작성) 6. 결정적이고 저비용인가? (아니오 → 하위 계층으로 이동) 7. 리팩터(행위 보존)를 견디는가? (아니오 → 행위 단정으로 재작성) 전부 YES → 유지 (의미 있는 RED) ``` > **뮤테이션은 '판정 보조 도구'** (05 §4 정책): 개별 테스트를 매번 뮤테이션으로 판정하면 비용 과다. 대신 리뷰에서 단정이 상수 교체·경계 반전을 잡는지 눈으로 검사하고, 정리(cleanup) 국면·금융/인가/안전 로직에서만 뮤테이션(변경 파일 증분)으로 확인한다. > (레드팀 정정: 기존 "최종 판정기" 표현은 05와 모순 — 통일)