TDD / TDD란 무엇인가?
본 글은 최범균 님의 테스트 주도 개발 시작하기를 읽으며 작성한 글입니다.
테스트 주도 개발 시작하기
TDD(Test-Driven Development)는 테스트부터 시작한다. 구현을 먼저 하고 나중에 테스트하는 것이 아니라 먼저 테스트를 하고 그다음에 구현한다. 구현 코드가 없는데 어떻게 테스트할 수 있을까? 여기
www.yes24.com
TDD 이전의 개발
테스트 주도 개발을 배우기 전에 개발하던 방식은 대략 다음과 같았다.
- 만들 기능에 대해 설계를 고민한다. 어떤 클래스와 인터페이스를 도출할지 고민하고, 각 타입에 어떤 메서드를 넣을지 생각한다.
- 과정 1을 수행하며 설계가 머릿속에 그려지면 코드를 작성한다.
- 구현이 완료된 것 같으면 테스트 코드를 작성하며, 문제가 있으면 이 과정을 반복하며 해결한다.
TDD란?
TDD는 기능 구현이 아닌 테스트부터 시작한다. 그럼 의문점이 생긴다. "구현 코드가 없는데 어떻게 테스트를 하지?" 여기서 테스트를 먼저 한다는 것은 기능이 올바르게 동작하는지 검증하는 테스트 코드를 작성한다는 것이다. 테스트 코드를 먼저 작성하고 테스트를 통과시키기 위해 구현 코드를 작성하는 방식으로 진행한다.
간단한 덧셈 기능을 TDD로 구현한 예제를 보면 이해하기 쉬울 것이다.
public class CalculatorTest {
@Test
void plus(){
int result = Calculator.plus(1,2);
Assertions.assertEquals(3,result);
}
}
작성 흐름은 아래와 같다.
- 덧셈 기능을 제공할 클래스, 메서드, 파라미터, 반환 타입에 대해 고민하고 int result = Calculator.plus(1,2) 코드를 작성한다.
- assertEquals 메서드를 사용해 예상 값과 실제값을 비교해준다.
- 구현한 코드가 없으니 당연하게도 코드에 컴파일 에러가 난다.
- 아래와 같이 Calculator 클래스와 plus 메서드를 만든다.
public class Calculator { public static int plus(int a, int b){ return 0; } }
- 테스트를 실행한다. 예상값과 실제값이 다르니 테스트는 실패한다.
- 테스트를 통과할 수 있도록 구현 코드를 고친다.
public class Calculator { public static int plus(int a, int b){ return 3; } }
- 테스트가 통과한다. 그럼 새로운 테스트를 작성한다.
public class CalculatorTest { @Test void plus(){ int result = Calculator.plus(1,2); Assertions.assertEquals(3,result); Assertions.assertEquals(5,Calculator.plus(2,3)); } }
- 테스트는 실패하게 되며, 통과될 수 있게 구현 코드를 변경한다.
public class Calculator { public static int plus(int a, int b){ return a+b; } }
- 모든 테스트를 실행시키면 모두 통과하는 것을 확인할 수 있다. 그럼 기능 구현이 완료된 것이다.
간단한 덧셈 기능을 TDD로 구현해 봤다.
간단한 기능을 이렇게까지 복잡하게 구현해야 하는지 의문이 들 것이다. 그러나 실무에서는 이런 간단한 기능이 아닌 복잡한 기능을 구현하게 될 것이다. 이럴 때 TDD는 빛을 발한다. 사람은 모든 예외 사항과 기능을 한 번에 구현하기 어렵고, 완성한다고 해도 테스트를 하면 실패할 확률이 크다. 테스트에 실패하면 결국 디버깅을 통해 문제점을 파악해야 하는데, 이러한 과정 속에서 개발자는 시간을 낭비하게 되고 코드도 품질도 떨어진다. 따라서 위와 같이 TDD 방식을 사용해 테스트를 먼저 작성하고 테스트에 실패하면 테스트를 통과시킬 만큼 코드를 추가하는 과정을 반복하면서 점진적으로 기능을 완성해 나가면 된다.
이런 과정을 그림으로 보면 아래와 같다.
TDD의 장점
경험은 별로 없지만 TDD 방식의 가장 큰 장점은 두 가지로 나눌 수 있을 것 같다.
1. 지속적인 코드 정리
테스트가 성공하면 리팩토링을 진행한다. 리팩토링할 대상이 눈에 들어오면 바로 리팩토링을 하고, 생각이 나지 않으면 다음 테스트를 진행한다. 테스트 코드를 작성하지 않을 때는 코드를 수정하기가 꺼려졌다. 하지만 테스트 코드가 있어 코드를 수정하는데 불안함이 없고 오히려 과감하게 리팩토링을 하게 된다. 이런 마음가짐(?)과 계속 코드를 정리해 코드가 굉장히 깔끔해지는 것을 볼 수 있었다.
2. 빠른 피드백
테스트 코드가 존재하기 때문에 새로운 기능을 넣거나 기존 코드를 수정했을 때 어떤 부분에 문제가 있는지 빠르게 알 수 있다. 따라서 디버깅하는 시간이 매우 단축된다. 테스트 코드가 없이 디버깅하며 문제점을 찾는 것은 상상만 해도 너무 끔찍하다..
댓글