뭘 테스트해야 하는지 몰랐던 시절
100% 커버리지를 목표로 삼았다가 시간만 날린 이야기. 테스트 전략은 따로 있었다.
커버리지 100%를 향해 달렸다
첫 회사에서 테스트를 처음 작성했을 때, 시니어가 "커버리지 높이라"고 했다. 그래서 진짜 다 테스트했다. 유틸 함수, 컴포넌트 렌더링, 버튼 클릭, 심지어 CSS 클래스가 잘 붙는지까지. 3주 동안 테스트만 248개를 짰다.
커버리지 94%를 찍었다. 기분이 좋았다. 근데 다음 달에 실제 프로덕션 버그가 3건 터졌고, 그중 하나도 내 테스트로 잡히지 않았다.
테스트가 잡지 못한 버그들
첫 번째 버그는 API 응답 형식이 바뀌었는데 프론트가 옛날 형식을 기대하고 있었던 거다. 두 번째는 결제 플로우에서 특정 조건일 때 리다이렉트가 안 되는 거였다. 세 번째는 동시 요청 시 데이터가 꼬이는 레이스 컨디션.
내가 열심히 테스트한 건 "버튼을 누르면 모달이 열린다", "input에 값을 넣으면 state가 바뀐다" 같은 것들이었다. 중요하지 않다는 게 아니라, 실제로 문제가 터지는 곳은 그런 데가 아니었다.
(248개의 테스트 중 실제 버그를 잡아준 건 0개라니.)
뭘 테스트해야 하는지 깨달은 순간
결국 돈이 오가는 곳, 사용자 데이터가 변하는 곳, 복잡한 비즈니스 로직이 있는 곳. 여기가 테스트의 우선순위다. "이 테스트가 없으면 배포가 무서운가?" 이 기준으로 판단하니까 뭘 테스트해야 하는지 명확해졌다.
단위 테스트 200개보다 핵심 플로우를 검증하는 통합 테스트 15개가 더 가치있을 때가 많다.
TDD를 시도했다가 포기한 이야기
사실 TDD도 해봤다. 2주 정도. 테스트를 먼저 작성하고 코드를 짜는 방식인데, 문제는 요구사항이 계속 바뀌는 환경에서 테스트를 먼저 쓰면 테스트도 같이 계속 바뀐다는 거다.
PM이 "이 기능 좀 다르게 바꿔주세요" 할 때마다 코드보다 테스트를 먼저 고쳐야 했다. 기능 하나 수정하는데 테스트 수정 시간이 더 길어지는 본말전도가 일어났다. 결국 포기했다.
근데 순수 함수나 유틸리티 같은 건 TDD가 잘 맞긴 했다. 입출력이 명확하니까.
지금 쓰는 테스트 전략
통합 테스트 중심으로 가되, 핵심 비즈니스 로직은 단위 테스트를 짠다. E2E는 결제나 회원가입 같은 크리티컬 플로우만. 비율로 따지면 통합 60%, 단위 30%, E2E 10% 정도.
커버리지 숫자는 안 본다. 대신 "이 PR에서 뭐가 깨질 수 있는지" 기준으로 테스트를 추가한다. 이렇게 바꾸고 나서 프로덕션 버그가 월 3건에서 0-1건으로 줄었다.
지금도 확신은 없다
솔직히 이게 정답인지는 모르겠다. 프로젝트 성격에 따라 달라질 수 있고, 팀 규모에 따라서도 다를 거다. 테스트 전략에 정답이 있다고 말하는 사람을 좀 의심하게 됐다. 다 자기 상황에 맞는 답이 있을 뿐이다.