TDD: Test Driven Development란?
프로덕션 코드보다 테스트 코드를 먼저 작성하여 테스트가 구현 과정을 주도하도록 하는 방법론
즉, 기능 구현보다 테스트를 먼저 구현하고, 기능을 구현하거나 수정할 때 테스트 코드의 도움을 받을 수 있는 방식을 의미한다.
Red-Green-Refactor
TDD의 방법으로는 Red, Green, Refactor를 주로 언급한다.
- Red: 실패하는 테스트를 먼저 작성. → 기능 구현이 돼있지 않기에 테스트가 실패하는 것이 당연하다.
- Green: 빠른 시간 내에 테스트를 통과하는 최소한의 기능 구현하기. → 초록불을 볼 수만 있다면, 이 단계에서의 구현은 다소 엉터리여도 된다.
- Refactor: 테스트 통과 상태를 유지하면서 구현 코드를 개선해나간다.
Red-Green-Refactor로 코딩하는 예시
1. Red
담긴 음료들의 가격 총합을 구하는 calculateTotalPrice
메서드를 TDD로 구현해보자.
우선 현재 calculateTotalPrice 메서드는 아래와 같이 구현이 돼있지 않은 상태이다.
public int calculateTotalPrice() {
return 0;
}
이제 빨간 불이 뜨는, 즉 통과하지 않는 테스트 코드를 짜보자.
@Test
void calculateTotalPrice() {
CafeKiosk cafeKiosk = new CafeKiosk();
Americano americano = new Americano();
Latte latte = new Latte();
cafeKiosk.add(americano);
cafeKiosk.add(latte);
int totalPrice = cafeKiosk.calculateTotalPrice();
assertThat(totalPrice).isEqualTo(8500);
}
이 테스트를 지금 돌리면 당연히도 실패한다.
로직이 구현돼 있지 않아 항상 0을 리턴하기 때문이다.
2. Green
그러면 빠른 시간 내에 테스트를 통과하는 코드를 작성해보자.
“빠른 시간 내에”가 핵심이다.
public int calculateTotalPrice() {
return 8500;
}
이렇게 하면 어쨌든 테스트를 통과 시킬 수 있다.
3. Refactor
그러면 이제 테스트 통과 상태를 유지하면서 더 좋은 코드로 고쳐나가자
public int calculateTotalPrice() {
int totalPrice = 0;
for (Beverage beverage : beverages) {
totalPrice += beverage.getPrice();
}
return totalPrice;
}
이렇게 제대로 된 기능이 구현된 코드로 고칠 수 있을 것이다.
여기서 테스트 통과 상태를 유지하면서 한번 더 리팩토링을 할 수도 있다.
스트림을 통해서 코드를 더 깔끔하게 개선해보자.
public int calculateTotalPrice() {
return beverages.stream()
.mapToInt(Beverage::getPrice)
.sum();
}
이런 red → green → refactor 사이클을 거치며 코드를 더 나은 코드로 개선해 나갈 수 있다.
TDD의 핵심 가치
TDD의 핵심 가치는 피드백이라고 할 수 있을 것이다.
내가 작성하는 Production Code에 대해 자주, 빠른 피드백을 받을 수 있다.
선 기능 구현, 후 테스트로 구현했을 때의 단점은 뭘까?
바로 해피 케이스에 대해서만 생각하며 구현하다가 잘못된 로직을 구현할 수 있다.
TDD로 개발하면 이러한 상황을 방지할 수 있을 것이다.
반대로 TDD로 구현을 했을 때는 어떤 이점을 볼 수 있을까?
- 복잡도가 낮은(=유연하고 유지보수 쉬운), 테스트가 쉬운 코드를 작성할 수 있게 된다.
- 쉽게 발견하기가 어려운 엣지 케이스를 놓치지 않고 구현할 수 있도록 해준다.
- 클라이언트(외부 객체) 관점에서의 코드를 작성할 수 있다.
Reference
'개념 공부 > Test Code' 카테고리의 다른 글
[Test Code / Java] Spring 프로젝트에서 Persistence Layer의 테스트 (0) | 2024.12.29 |
---|---|
[Test Code / Java] @DisplayName과 BDD (2) | 2024.12.28 |
[Test Code / Java] 단위 테스트 (1) | 2024.12.26 |