TDD(Test-Driven Development)는 테스트를 먼저 작성하고, 그 테스트를 통과하는 최소한의 코드를 작성한 후, 리팩토링을 통해 코드를 개선하는 개발 방법론입니다.
TDD는 다음 3단계를 반복하는 사이클로 진행됩니다:
🔴 Red: 실패하는 테스트 작성
🟢 Green: 테스트를 통과하는 최소한의 코드 작성
🔵 Refactor: 코드 개선
TDD의 Red-Green-Refactor 사이클을 실제로 체험해보겠습니다.
먼저 덧셈 기능을 테스트하는 코드를 작성합니다.
// CalculatorTest.java
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class CalculatorTest {
@Test
void 두_수를_더한다() {
// Given
Calculator calculator = new Calculator();
// When
int result = calculator.add(2, 3);
// Then
assertEquals(5, result);
}
}
이 시점에서는 Calculator 클래스가 없어서 컴파일 에러가 발생합니다. 이것이 바로 🔴 Red 단계입니다!
이제 테스트를 통과시키기 위한 최소한의 코드를 작성합니다.
// Calculator.java
public class Calculator {
public int add(int a, int b) {
return a + b;
}
}
테스트가 통과합니다! 🟢 Green 단계 완료!
현재는 코드가 간단해서 리팩토링할 부분이 없습니다. 다음 기능으로 넘어가겠습니다.
@Test
void 두_수를_뺀다() {
// Given
Calculator calculator = new Calculator();
// When
int result = calculator.subtract(5, 2);
// Then
assertEquals(3, result);
}
subtract 메서드가 없어서 컴파일 에러 발생! 🔴 Red 단계
public class Calculator {
public int add(int a, int b) {
return a + b;
}
public int subtract(int a, int b) {
return a - b;
}
}
테스트 통과! 🟢 Green 단계 완료
여전히 간단해서 리팩토링할 부분이 없습니다.
TDD에서 가장 중요한 원칙 중 하나는 작은 단위로 나누어 개발하는 것입니다.
@Test
void 복잡한_계산을_한번에_테스트() {
Calculator calc = new Calculator();
// 여러 기능을 한 번에 테스트하려고 시도
double result = calc.calculate("(10 + 5) * 2 - 3 / 1.5");
assertEquals(27.0, result);
}
@Test
void 덧셈_테스트() {
Calculator calc = new Calculator();
assertEquals(15, calc.add(10, 5));
}
@Test
void 곱셈_테스트() {
Calculator calc = new Calculator();
assertEquals(30, calc.multiply(15, 2));
}
@Test
void 뺄셈_테스트() {
Calculator calc = new Calculator();
assertEquals(27, calc.subtract(30, 3));
}
왜 작은 단위가 중요한가?
// ❌ Bad
@Test
void test1() {}
// ✅ Good
@Test
void 음수를_입력하면_예외가_발생한다() {}
TDD는 단순히 테스트를 먼저 작성하는 것이 아니라, 더 나은 설계와 안정적인 코드를 만들기 위한 개발 방법론입니다. 처음에는 번거로울 수 있지만, 익숙해지면 개발 속도와 코드 품질 모두를 향상시킬 수 있는 강력한 도구가 됩니다.
중요한 것은 완벽한 TDD보다는 점진적인 적용과 지속적인 개선입니다. 작은 기능부터 시작해서 천천히 TDD 문화를 만들어가시길 추천드립니다!
참고자료