책/테스트 주도 개발 시작하기(완)
2장 TDD 시작
sami355
2024. 7. 3. 17:19
TDD란?
- TDD는 기능을 검증하는 테스트 코드를 먼저 만든다고 했다.
- 테스트 대상이 될 클래스 이름, 메서드 이름, 파라미터 개수, 리턴 타입을 고민했다. 또한 새로운 객체를 생성할지 아니면 정적 메서드로 구현할지 등을 함께 고민했다.
- 테스트 코드를 작성한 뒤에는 컴파일 오류를 없애는 데 필요한 클래스와 메서드를 작성했다. 그런 뒤 바로 테스트를 실행했고 테스트에 실패했다.
- 테스트를 통과할 만큼만 코드를 구현했다.
- 실패한 테스트를 통과시킨 뒤에 새로운 테스트를 추가했고 다시 그 테스트를 통과시키기 위한 코드를 작성했다.
- 존재하지 않는 클래스의 이름을 고민하며 바로 테스트 코드를 작성했다.
TDD 예: 암호검사기
(기능 요구사항이 주어진 상황입니다.)
- 테스트할 기능의 이름을 정해보자
- 검사를 한다는 의미를 표한할 단어를 찾자.
첫번째 테스트: 모든 규칙을 충족하는 경우
- 첫 번째 테스트 코드를 통과하는 시간도 길어진다. -> 테스트 주기를 빠르게 해야 한다.
- 각 조건을 검사하는 코드를 마들지 않고 '강함'에 해당하는 값을 리턴하면 테스트를 통과할 수 있다. -> 어떤 값이 들어오든 '강함'에 해당하는 값을 리턴
- TDD는 테스트를 통과시킬만큼의 코드를 작성한다.
두번째 테스트: 길이만 8글자 미만이고 나머지 조건은 충족하는 경우
- 두 테스트를 모두 통과시킬 수 있는 만큼 코드를 작성해 보자.
세번째 테스트: 숫자를 포함하지 않고 나머지 조건은 충족하는 경우
- 이 테스트를 통과하는 방법은 어렵지 않다. 암호가 숫자를 포함했는지를 판단해서 포함하지 않은 경우 NORMAL을 리턴하게 구현하면 된다.
코드 정리: 테스트 코드 정리
- 테스트 코드도 코드이기 때문에 유지보수 대상이다.
- 코드를 수정한 뒤에 테스트에 통과하는지 확인함으로써 안전하게 코드를 수정할 수 있다.
- 테스트 코드의 중복을 무턱대고 제거하면 안 된다. 중복을 제거한 뒤에도 테스트 코드의 가독성이 떨어지지 않고 수정이 용이한 경우에만 중복을 제거해야 한다. 중복을 제거한 뒤에 오히려 테스트 코드 관리가 어려워진다면 제거했던 중복을 되돌려야 한다.
네번째 테스트: 값이 없는 경우
- 코드를 구현하기에 앞서 검증하는 테스트 코드를 먼저 추가한다.
다섯번째 테스트: 대문자를 포함하지 않고 나머지 조건을 충족하는 경우
- 테스트를 실행하면 새로 추가한 검증 코드에서 실패할 것이다. 실패한 코드를 통과시킬 차례이다.
여섯번째 테스트: 길이가 8글자 이상인 조건만 충족하는 경우
- 이제 어떤 경우를 테스트해야 하나? 이제 남은 것은 한 가지 조건만 충족하거나 모든 조건을 충족하지 않는 경우이다.
- if절의 위치를 이동한 이유는 다음 두 로직을 구분해서 모으기 위함이다.
- 개별 규칙을 검사하는 로직
- 규칙을 검사한 결과에 따라 암호 강도를 계산하는 로직
일곱번째 테스트: 숫자 포함 조건만 충족하는 경우
- 이를 검증하기 위한 테스트 코드를 추가한다.
여덟번째 테스트: 대문자 포함 조건만 충족하는 경우
- 대문자 포함 조건만 충족하는 경우를 검증하는 테스트를 추가할 차례다.
아홉번째 테스트: 아무 조건도 충족하지 않은 경우
- 지금까지 새로운 테스트를 추가하거나 기존 코드를 수정하면 습관처럼 테스트를 실행했다. 그리고 실패한 테스트가 있다면 그 테스트를 통과시키기 위한 코드를 추가했다.
코드 정리: 코드 가독성 개선
- meter() 메서드의 가독성이 좋아졌다. meter() 메서드를 처음보는 개발자도 다음과 같이 코드를 읽을 수 있다.
테스트에서 메인으로 코드 이동
- src/test/java 소스 폴더는 배포 대상이 아니므로 이 두 소스 파일을 src/main/java로 이동해야 비로서 구현이 끝난다.
TDD 흐름
- TDD는 기능을 검증하는 테스트를 먼저 작성한다. 작성한 테스트를 통과하지 못하면 테스트를 통과할 만큼만 코드를 작성한다. 테스트를 통과한 뒤에는 개선할 코드가 있으면 리팩토링한다.
- 리팩토링을 수행한 뒤에는 다시 테스트를 실행해서 기존 기능이 망가지지 안았는지 확인한다. 이 과정을 반복하면서 점진적으로 기능을 완성해 나가는 것, 이것이 전형적인 TDD의 흐름이다.
테스트가 개발을 주도
- 테스트를 추가한뒤에는 테스트를 통과시킬 만큼 기능을 구현했다. 지금까지 작성한 테스트를 통과할 만큼만 구현을 진행했다.
- 테스트 코드를 만들면 다음 개발 범위가 저해진다. 테스트 코드가 추가되면서 검증하는 범위가 넓어질수록 구현도 점점 완성되어간다.
지속적인 코드 정리
- 구현을 완료한 뒤에는 리팩토링을 진행했다. 리팩토링할 대상이 눈에 들어오면 리팩토링을 진행해서 코드를 정리했다.
빠른 피드팩
- TDD가 주는 이점은 지속적으로 코드 수정에 대한 피드백이 빠르다는 점이다.