테스트 코드를 작성해 본 적은 있지만 TDD를 경험해본 적은 없었는데 이번에 TDD 관련 책을 읽게 되어 공부한 내용을 정리해보려고 한다.
테스트 주도 개발 시작하기 - 최범균 저
TDD 시작
TDD 이전의 개발
개발 과정
- 만들 기능에 대한 설계 및 구현에 대해 고민한다.
- 한 번에 코드를 구현한다.
- 기능 구현이 완료되면 기능을 테스트한다.
- 테스트 과정에서 문제가 발생하면 작성한 코드를 디버깅하면서 원인을 찾고, 코드를 수정한다.
- 테스트-디버깅-코드수정 과정을 반복한다.
문제점
한 번에 작성하는 코드가 많다.
- 문제 발생 시 원인 파악을 위해 확인해야 할 코드가 많아진다.
- 그래서 디버깅하는 시간도 길어진다.
- 이는 결국 개발 속도의 저하로 이어진다.
TDD란?
TDD(Test-Driven Development)란 기능이 올바르게 동작하는지 검증하는 테스트 코드를 먼저 작성하고 나서, 테스트를 통과시키기 위한 개발을 진행하는 방식이다. 테스트를 먼저 작성하고 테스트에 실패하면 테스트를 통과시킬 만큼 코드를 추가하는 과정을 반복하면서 점진적으로 기능을 완성해간다.
TDD 흐름
- 테스트 코드 작성 -> 코딩 -> 리팩토링을 반복하는 사이클을 가진다.
- TDD의 사이클을 Red -> Green -> Refactor 로 부르기도 한다.
TDD의 이점
이렇게 테스트가 개발을 주도함으로써 얻게 되는 이점에는 다음과 같은 것들이 있다.
- 테스트 코드를 작성하는 과정에서 기능 구현을 위한 설계 요소들을 먼저 고민하게 된다.
- 코드가 추가/수정될 때마다 테스트를 돌려 올바른지 바로 확인할 수 있다.
- TDD는 개발 과정에서 지속적으로 리팩토링을 하므로 코드 품질이 나빠지는 것을 방지하고, 유지보수 비용을 낮춘다.
테스트 코드 작성
테스트 코드 작성 순서
- 구현하기 쉬운 테스트부터 시작해서 점점 어려운 테스트로 진행
- 처음부터 어려운 테스트부터 통과할 목적으로 구현하려고 하면 한 번에 많은 코드를 구현해야 한다. 따라서 디버깅 시간도 길어진다.
- 쉬운 테스트부터 시작하면 한 번에 만들어야 할 코드가 적고, 빠르게 구현하고 테스트할 수 있다. 따라서 디버깅 할 때도 유리하다.
- 예외적인 경우에서 정상적인 경우로 진행
- 많은 기능을 완성해놓고 나중에 예외 상황을 고려하면 코드 구조가 많이 바뀔 가능성이 높다.
- 초반에 예외 상황을 테스트하여 코드에 반영하면, 예외 상황에 따라 발생하는 버그도 줄여준다.
- 예외적인 상황을 미리 고민하고 찾는 과정을 통해 버그 발생 가능성을 사전에 파악할 수 있다.
점진적 구현
테스트를 만들고, 구현하는 과정에서 막힌다면 다음과 같이 점진적으로 구현해 보자.
- 테스트에서 정해진 상수 값을 리턴
- 값 비교를 이용해서 정해진 값을 리턴
- 다양한 테스트 케이스를 추가하면서 구현을 일반화
리팩토링 시점
상수를 변수로 바꾸거나, 변수 이름을 변경하는 것과 같은 작은 리팩토링은 발견하면 바로 실행한다. 반면에, 메서드 추출과 같이 메서드의 구조에 영향을 주는 리팩토링은 큰 틀에서 구현 흐름이 눈에 들어오기 시작한 뒤에 진행한다.
테스트 목록 정리하기
- TDD를 시작할 때 테스트할 목록을 미리 정리하면 좋다.
- 테스트 과정에서 새로운 테스트 사례를 발견하면 그 사례를 목록에 추가해서 놓치지 않도록 한다.
- 테스트할 목록을 적었다고 해서 테스트를 한 번에 다 작성하면 안 된다. (하나씩 TDD 사이클로 진행)