빨간 막대는 실패하는 테스트다. 이 장은 그 실패를 언제 만들고, 어떤 크기로 잡고, 막혔을 때 어떻게 빠져나오는지를 다룬다. 기법이라기보다 작업 리듬에 대한 패턴들이다 — 특히 마지막 두 개(휴식, 다시 하기)는 코드가 아니라 사람에 대한 조언이다.
한 번에 얼마나 나아가는가
한 단계 테스트. 목록에서 다음 테스트를 고를 때, 지금 무언가를 새로 가르쳐 주면서도 확실히 통과시킬 수 있는 것을 고른다. 걸음이 너무 크면 추측이 끼어들고, 너무 작으면 지루하다. 흥미로운 것과 자신 있는 것 사이의 균형점을 찾는다. 이 균형 감각 자체가 경험으로 는다.
판단 기준: “이걸 통과시키는 법이 지금 머리에 그려지는가?”가 예스이면 적절한 크기다. 함정: 한 테스트에 두 가지 새 개념을 동시에 넣으면 빨강의 원인이 둘로 갈려 진단이 흐려진다.
어디서 시작하는가
시작 테스트. 오퍼레이션의 가장 단순하고 대표적인 사례가 아니라, 실제로 만들었을 때 무언가를 가르쳐 주는 가장 작은 것에서 시작한다. 종종 그것은 “아무것도 없는” 경우 — 빈 목록, 0, 널 — 이다. 시작이 작을수록 첫 초록까지의 거리가 짧다.
설명 테스트. 자동화된 테스트가 널리 쓰이지 않는 조직에서, 말로 하던 설명을 테스트로 바꿔 요청하고 답한다. “A일 때 B가 되죠?”를 테스트 코드로 주고받으면 오해가 준다. 테스트는 실행 가능한 합의 문서다.
# 시작 테스트 — "빈 것"에서 출발하면 첫 초록이 가장 가깝다
def test_empty_sum():
assert Portfolio().sum() == 0판단 기준: 첫 테스트로 무엇을 배웠는지 한 문장으로 말할 수 있어야 좋은 시작 테스트다. 함정: 화려한 대표 사례로 시작하면 껍데기를 만드는 데만 한참 걸려 리듬이 안 붙는다.
배우기 위해 테스트를 쓴다
학습 테스트. 처음 쓰는 외부 라이브러리·API의 동작이 궁금할 때, 문서를 읽는 대신 그 API를 호출하는 테스트를 써서 실제 반환을 확인한다. 이 테스트는 라이브러리 버전이 바뀌었을 때 우리 가정이 깨졌는지도 잡아 준다. 즉 학습이 회귀 방어로 남는다.
또 다른 테스트. 대화 도중 곁길 아이디어가 떠오르면, 논의를 멈추지 말고 목록에 “또 다른 테스트”로 적어 둔다. 지금 주제를 지키면서 아이디어도 잃지 않는 방법이다.
판단 기준: 외부 코드에 대한 “아마 이렇게 동작할 것” 같은 가정이 있으면 그건 학습 테스트로 박제할 후보다. 함정: 학습 테스트를 학습만 하고 지워 버리면, 다음 버전 업 때 같은 조사를 처음부터 다시 한다.
나중에 발견한 결함
회귀 테스트. 버그 리포트가 들어오면, 그 버그를 드러내는 가장 작은 테스트부터 쓴다. 이 테스트가 초록이 되면 버그는 고쳐진 것이고, 그 테스트는 같은 버그의 재발을 영구히 막는다. 모든 버그는 “누락된 테스트”의 다른 이름이다.
회귀 테스트는 버그가 알려 준 “우리가 놓친 관점”을 코드로 붙잡는다. 하나의 버그는 대개 비슷한 이웃 버그를 데리고 있으므로, 회귀 테스트를 쓰는 김에 그 주변 경계도 함께 찔러 보면 이웃까지 딸려 나온다.
판단 기준: 버그를 고치기 전에 그 버그로 실패하는 테스트를 먼저 확인한다 — 안 그러면 정말 고쳤는지 알 수 없다. 함정: 테스트 없이 “고쳤다”고 넘어가면 리팩터링 한 번에 슬그머니 되살아난다.
막혔을 때 — 사람에 대한 패턴
휴식. 지치고 막히면 쉰다. 물을 마시거나 산책을 하는 동안 무의식이 문제를 정리한다. TDD가 주는 이점 하나는, 초록 막대와 커밋이라는 명확한 저장 지점이 있어 언제 쉬어도 되는지가 분명하다는 것이다.
다시 하기. 걸음이 계속 꼬이고 테스트가 복잡해지면, 지금까지의 코드를 미련 없이 버리고 처음부터 다시 한다. 방금 배운 것을 안고 다시 하면 두 번째는 훨씬 빠르고 깔끔하다. 코드는 잃어도 이해는 남는다.
판단 기준: 같은 테스트에서 30분 넘게 헤매면 대개 걸음 크기나 접근이 틀린 것 — 휴식이나 다시 하기를 꺼낼 때다. 함정: 매몰 비용에 매여 꼬인 코드를 억지로 살리려다 더 큰 시간을 쓴다. 버리는 것이 종종 더 싸다.
정리
- 빨간 막대 패턴의 절반은 코드가 아니라 리듬에 대한 것이다. 걸음 크기(한 단계 테스트)와 시작점(시작 테스트)을 잘 고르면 첫 초록까지의 거리가 짧아진다.
- 테스트는 검증만이 아니라 학습(학습 테스트)과 의사소통(설명 테스트)의 도구이기도 하다. 알아낸 것과 합의한 것을 실행 가능한 형태로 박제한다.
- 버그는 누락된 테스트다(회귀 테스트). 고치기 전에 실패하는 테스트부터 만든다.
- 막히면 사람을 돌본다 — 휴식과 다시 하기는 나약함이 아니라 전략이다. TDD의 명확한 저장 지점이 이 둘을 안전하게 만든다.
다음장으로 27장