우리들 대다수에게 단위 테스트란 자기 프로그램이 ‘돌아간다’라는 사실만 확인하는 일회성 코드에 불과했다.
에자일과 TDD 덕택에 단위 테스트를 자동화하는 프로그래머들이 이미 많아졌으며 점점 더 늘어나는 추세다. 하지만 우리 분야에 테스트를 추가하려고 급하게 서두르는 와중에 많은 프로그래머들이 제대로 된 테스트 케이스를 작성해야 한다는 좀 더 미묘한 (그리고 더욱 중요한) 사실을 놓쳐버렸다.
TDD 법칙 세 가지
첫째 법칙: 실패하는 단위 테스트를 작성할 때까지 실제 코드를 작성하지 않는다.
둘째 법칙: 컴파일은 실패하지 않으면서 실행이 실패하는 정도로만 단위 테스트를 작성한다.
셋째 법칙: 현재 실패하는 테스트를 통과할 정도로만 실제 코드를 작성한다.
위 세 가지 규칙을 따르면 개발과 테스트가 대략 30초 주기로 묶인다. 테스트 코드와 실제 코드가 함께 나올뿐더라 테스트 코드가 실제 코드보다 불과 몇 초 전에 나온다.
하지만 실제 코드와 맞먹을 정도로 방대한 테스트 코드는 심각한 관리 문제를 유발하기도 한다.
깨끗한 테스트 코드 유지하기
몇 년 전 나는 테스트 코드에 실제 코드와 동일한 품질 기준을 적용하지 않아야 한다고 명시적으로 결정한 팀을 코치해달라는 요청을 받았다. (…) ‘지저분해도 빨리’가 주제어였다.
하지만 팀은 지저분한 테스트 코드를 내놓으나 테스트를 안 하나 오십보 백보라는, 아니 오히려 더 못하다는 사실을 깨닫지 못했다. 문제는 실제 코드가 진화하면 테스트 코드도 변해야 한다는 데 있다.
실제 코드를 변경해 기존 테스트 케이스가 실패하기 시작하며, 지저분한 코드로 인해, 실패하는 테스트 케이스를 점점 더 통과시키기 어려워진다. 그래서 테스트 코드는 계속해서 늘어나는 부담이 되버린다.
하지만 테스트 슈트가 없으면 개발자는 자신이 수정한 코드가 제대로 도는지 확인할 방법이 없다. 테스트 슈트가 없으면 시스템 이쪽을 수정해도 저 쪽이 안전하다는 사실을 검증하지 못한다. 그래서 결함율이 높아지기 시작한다.
테스트에 쏟아 부은 노력은 확실히 허사였다. 하지만 실패를 초래한 원인은 테스트 코드를 막 짜도 좋다고 허용한 결정이었다.
테스트 코드는 실제 코드 못지 않게 중요하다. (…) 테스트 코드는 사고와 설계와 주의가 필요하다. 실제 코드 못지 않게 깨끗하게 짜야 한다.
테스트는 유연성, 유지보수성, 재사용성을 제공한다.
코드에 유연성, 유지보수성, 재사용성을 제공하는 버팀목이 바로 단위 테스트다. 이유는 단순하다. 테스트 케이스가 있으면 변경이 두렵지 않으니까!
테스트 케이스가 없다면 모든 변경이 잠정적인 버그다. (…) 하지만 테스트 케이스가 있다면 공포는 사실상 사라진다.
따라서 테스트 코드가 지저분하면 코드를 변경하는 능력이 떨어지며 코드 구조를 개선하는 능력도 떨어진다. 테스트 코드가 지저분할수록 실제 코드도 지저분해진다. 결국 테스트 코드를 잃어버리고 실제 코드도 망가진다.
깨끗한 테스트 코드
깨끗한 테스트 코드를 만들려면? 세 가지가 필요하다. 가독성,가독성,가독성
테스트 코드에서 가독성을 높이려면? 여느 코드와 마찬가지다. 명료성, 단순성, 풍부한 표현력이 필요하다. 테스트 코드는 최소의 표현으로 많은 것을 나타내야 한다.
🤔 오늘 읽은 소감은? 떠오르는 생각을 가볍게 적어보세요
단위 테스트 챕터의 일부분을 읽었다. 안타깝게도 나는 현재 ‘테스트 코드에 실제 코드와 동일한 품질 기준을 적용하지 않아야 한다고 명시적으로 결정한 팀’에 속해 있다. 우리 조직은 따로 테스트 코드를 작성하지 않는다.
이것이 지속 되었을 때, 운영 단계에서는 ‘히스토리’가 가장 중요해지는 문제가 발생한다. 단순히 코드만 보고서 이해하지 못하고, 왜 그렇게 처리했는지 과거의 이유를 기억하는 사람에게 의존해야 하는 것이다. 그렇기 때문에 새롭게 투입되는 개발자들도 코드 개선에 집중하며 코드로서 대화하는 것이 아니라, ‘히스토리’를 이해하고 그 흐름을 이어가는 데 치중하게 되는 것 같다. 그러다가 ‘히스토리’를 아는 사람이 퇴사라도 하는 날에는 주먹구구식으로 막는 것 말고는 방법이 없다…
깨끗한 테스트 코드의 필요성과 방법을 공부하며, 실무에서 이런 것을 경험해 보기 어렵다는 사실이 개인적으로 아쉬웠다. 앞으로 함께하는 팀이 더 나은 방향으로 나아가기 위해, 그리고 나 자신도 한층 성장하기 위해 어떻게 하면 좋을 지 고민이 많아지는 하루였다.
🔎 궁금한 내용이 있거나, 잘 이해되지 않는 내용이 있다면 적어보세요.
위 세 가지 규칙을 따르면 개발과 테스트가 대략 30초 주기로 묶인다?
이 부분이 무슨 말인지 처음에는 이해가 잘 되지 않았다. 하지만 여러 TDD 관련 포스팅들을 보고, 곱씹어서 읽어보니 조금은 이해가 되는 것 같기도 하다.
TDD의 절차를 보면 다음 그림과 같이 실패 테스트 코드 작성 → 통과 코드 작성 → Refactor
의 과정을 반복하면서 코드를 작성한다. 그러다 보니 테스트 코드와 실제 코드가 따로 따로 작성되는 것이 아니라, 굉장히 짧은 주기로 번갈아 가면서 작성 된다. 밥 아저씨는 TDD의 3가지 윈칙을 지켰는지 확인할 수 있는 간단한 방법을 이 문장으로 설명하고자 한게 아닌가 싶다.