테스트를 먼저 썼지만 바로 통과했습니다. 이것도 TDD의 Red-Green-Refactor라고 할 수 있을까요?
잠깐, 답변을 보기 전에
먼저 내 말로 설명해 볼까요?
답변과 점검 포인트 펼치기답변 접기
구두 답변
정의를 외우기보다, 원리와 조건을 연결해 설명해 보세요.
TDD의 핵심 순서는 요구사항을 드러내는 실패 테스트를 먼저 만들고, 그 테스트가 실패하는 것을 확인한 뒤, 통과에 필요한 최소 구현만 하고, 마지막으로 동작을 유지한 채 구조를 개선하는 Red-Green-Refactor 반복입니다. 테스트 파일을 코드보다 먼저 작성했다는 사실만으로 충분하지 않습니다. 새 테스트가 실제로 잘못된 구현을 잡을 수 있는지 실패를 확인해야 하기 때문입니다.
예를 들어 할인 규칙에 ‘주문 금액이 5만 원 이상이면 10% 할인’이라는 사례를 추가했다면 처음에는 구현이 없거나 기존 결과가 달라 테스트가 실패해야 합니다. 그다음 임계값을 만족하는 최소 로직으로 통과시키고, 통과 후 이름·중복·구조를 정리합니다. 리팩터 단계에서는 외부에서 관찰되는 결과와 기존 테스트를 유지해야 하며, 새 기능을 더하는 단계와 동작을 바꾸지 않는 정리 단계를 섞지 않겠습니다.
테스트를 먼저 작성했는데도 즉시 통과했다면 이미 구현된 계약을 확인한 것일 수 있고, 테스트가 너무 약해 실패를 잡지 못했을 수도 있습니다. 그 경우 경계값이나 반대 사례를 추가하고, 의도적으로 구현을 깨서 테스트가 실패하는지 확인하겠습니다. TDD는 높은 커버리지나 버그 부재를 보장하는 방법이 아니며, 외부 시스템 계약은 통합 테스트가 필요합니다. 테스트를 위한 구조 변경이 검증하려는 로직의 복잡성보다 커진다면 핵심 규칙과 실패 비용이 큰 부분부터 적용하겠습니다.
Red는 테스트의 검출력을 확인합니다
테스트를 먼저 썼는데 즉시 통과했다면 이미 구현된 계약을 확인한 것일 수도 있지만 반례가 약한 것일 수도 있습니다. 할인 임계값 49,999·50,000·50,001, 할인 불가 입력과 잘못된 상태를 추가하고, 구현을 의도적으로 깨뜨렸을 때 실패하는지 봅니다. 한 번의 결함 주입과 여러 변형을 자동 적용해 검출률을 재는 mutation testing은 Red 확인을 체계화한 별도 기법입니다.
단계별 변경을 보존합니다
Green에서는 통과에 필요한 최소 구현만 하고, Refactor에서는 결과·예외·상태 불변식을 유지한 채 이름과 중복을 정리합니다. 테스트가 private 메서드나 호출 횟수에 묶이면 외부 결과와 계약을 검증하도록 바꿉니다. 외부 API는 가짜 구현으로 정책의 빠른 피드백을 얻고, 실제 직렬화·timeout·DB 제약은 계약·통합 시험으로 보완합니다. 테스트가 명세 자체를 검증하지는 않으므로 요구사항의 반대 사례와 운영 경계를 별도로 확인하겠습니다.
구체적인 경계 사례
Red에서 문법 오류나 의존성 누락으로 실패한 것은 할인 규칙을 검출했다는 증거가 아닙니다. 테스트가 의도한 assertion에서 실패하는지 확인해야 합니다. Green에서 예제 하나만 하드코딩해 통과할 수 있다면 다음 예제와 경계값을 추가해 일반 규칙을 드러내되, 아직 합의하지 않은 미래 기능까지 구현하지 않습니다.
테스트 구조를 정리하는 Refactor도 제품 코드를 정리할 때처럼 작은 단계로 진행합니다. 기대값 계산에 제품과 같은 할인 함수를 재사용하면 같은 오류를 공유하므로 독립적인 명시 값이나 다른 기준 계산을 씁니다. 라인 커버리지는 실행 여부이고 검출력은 assertion이 어떤 오동작을 거절하는지의 문제입니다. 변이 테스트에서도 의미가 같은 변이와 실제 놓친 결함을 구분해 결과를 해석하겠습니다.
득점 포인트
이해가 드러나는 지점을 확인해 보세요.
- Red의 실패를 테스트 검출력 확인으로, Green과 Refactor를 별도 단계로 설명한다.
- 경계값·반례·mutation testing과 외부 계약·통합 테스트를 구분한다.
- 구현 세부사항보다 결과·예외·상태 불변식을 검증한다.
감점 포인트
놓치기 쉬운 조건과 오해를 짚어 보세요.
- 테스트 파일을 먼저 만들면 실패 확인 없이도 TDD라고 한다.
- Green에서 미래 요구까지 구현해 최소 피드백 고리를 늘린다.
- 테스트가 명세 오류·외부 계약·테스트 범위 밖의 모든 버그를 제거한다고 과장한다.
더 파고들 거리
하나 더 질문하며 이해의 범위를 넓혀 보세요.
- 테스트 검출력을 확인하려고 코드를 의도적으로 바꿉니다. mutation testing의 생존 변이와 동등 변이는 어떻게 해석하나요?
- 외부 API를 사용하는 코드를 TDD로 다룰 때 단위 테스트와 계약·통합 테스트를 어떻게 나눌까요?
- 테스트가 리팩터링을 방해하는 경우 테스트가 구현 세부사항에 결합됐는지 어떻게 판단할까요?
득점·감점 포인트는 학습용 자기 점검 기준이며, 특정 회사의 실제 채점표가 아닙니다.
원리부터 공부하고 싶다면
답변을 보충하는 개념·예제·슈도코드를 읽어 보세요.