TDD란?


TDD란 Test Driven Development 의 약자로 테스트 주도 개발이라고 한다.

TDD 개발 주기

  1. RED - 실패하는 테스트 코드 작성
  2. GREEN - 테스트 코드를 성공시키기 위한 최소한의 코드 작성
  3. YELLOW - 리팩터링 및 커밋 타이밍

일반 개발 방식과의 차이

일반적인 개발 방식은 요구사항 분석 → 설계 → 개발 → 테스트 → 배포 순의 개발 주기를 갖고 있다.

이러한 개발 방식의 단점은 소프트웨어 개발을 느리게 하는 잠재적 위험이 존재한다는 것이다.

어느 프로젝트던 초기에 완벽한 설계는 없다. 개발 도중 디자인의 오류나 요구사항의 변경 등 내외부적인 조건들을 개선하며 점진적으로 완벽한 설계로 나아가는 것이 일반적이기 때문에 재설계로 인해 발생하는 코드 품질의 저하테스트 비용이 증가하는 문제들을 야기할 수 있다.

결론적으로 일반 개발 방식으로 개발한 소프트웨어의 경우 재사용이 어려운 코드들이 포함될 가능성이 크며 관리가 어려워 유지 보수를 힘들게 만들 수 있다.

TDD와 일반 개발 방식의 가장 큰 차이점은 테스트 코드를 먼저 작성한다는 점에 있다.

디자인 및 설계 단계에서 프로그래밍 목적을 미리 정의하고 무엇을 테스트해야 하는지 정의하여 테스트 케이스를 작성해야 한다.

테스트 코드 작성 중 발생하는 예외 사항들은 테스트 케이스를 추가하여 설계를 개선한다.

이후 테스트가 통과된 코드들만 실제 코드로 작성한다.

위와 같은 반복적인 단계가 진행되면서 자연스럽게 버그가 줄어들고, 소스코드가 간결해진다.

TDD 개발 방식의 장점


보다 튼튼한 객체 지향적인 코드 생성

TDD 개발 방식으로 작성한 코드는 재사용 보장을 명시하므로 기능 별 철저한 모듈화가 이루어진다.

이는 종속성과 의존성이 낮은 모듈로 조합된 소프트웨어를 개발하게 하여 필요에 따라 모듈을 추가하거나 제거해도 소프트웨어 전체적인 구조에 영향을 미치지 않게 된다.

재설계 시간 단축

테스트 코드를 먼저 작성하기 때문에 다양한 예외사항에 대해 생각해 볼 수 있고 현재 개발 단계를 정확히 정의하고 개발할 수 있게 된다.

이는 개발 도중 전반적인 설계가 변경되는 일을 방지할 수 있다.

디버깅 시간 단축

이는 단위 테스트 사용의 이점이기도 하다. 가령 사용자의 데이터가 잘못 나올 경우 모든 레이어를 전부 디버깅할 필요 없이 자동화 된 단위 테스트로 특정 버그를 손 쉽게 찾아낼 수 있다.

테스트 문서의 대체 가능

프로젝트 진행 과정에서 테스트 정의서를 만들 필요 없이 테스팅을 자동화함과 동시에 정확한 테스트 근거를 산출할 수 있다.

추가 구현의 용이함

개발이 완료된 소프트웨어에 추가 기능을 구현할 때 기존 코드에 어떤 영향을 미칠지 알지 못한다.

TDD 개발 방식을 채택한 경우 자동화된 단위 테스트를 전제하므로 테스트 기간을 단축할 수 있다.

TDD 개발 방식의 단점


생산성의 저하

처음부터 2개의 코드를 작성해야 하고, 중간중간 테스트를 하면서 고쳐나가기 때문에 개발 속도가 일반 개발 방식에 비해 10~30% 정도 늘어난다.

단위 테스트란?


단위 테스트란, 하나의 모듈을 기준으로 독립적으로 진행되는 가장 작은 단위의 테스트이다.

여기서 모듈은 애플리케이션에서 작동하는 하나의 기능 또는 메서드로 볼 수 있다.

즉, 단위 테스트는 애플리케이션을 구성하는 하나의 기능을 독립적으로 테스트하는 것으로, 어떤 기능이 실행되면 어떤 결과가 나온다 정도의 테스트를 진행한다.

JUnit 테스트 메서드명에는 메서드명_테스트상태_기대행위 와 같이 언더스코어로 구분 할 수 있다.

단위 테스트의 필요성


단위 테스트는 통합 테스트와 다르게 해당 부분만 독립적으로 테스트하기 때문에 어떤 코드를 리팩터링하여도 빠르게 문제 여부를 확인할 수 있다.

단위 테스트를 채택하여 개발을 진행할 경우 아래와 같은 이점들을 얻을 수 있다.

  • 테스팅에 대한 시간과 비용을 절감할 수 있다.
  • 새로운 기능 추가 시 수시로 빠르게 테스트할 수 있다.
  • 리팩터링 시 안정성을 확보할 수 있다.
  • 코드에 대한 문서가 될 수 있다.

좋은 단위 테스트의 특징


일반적으로 요구 사항은 계속해서 변하기 때문에 그에 맞춰 코드 역시 변경되어야 한다.

변경된 코드는 잠재적 오류를 내포하고 있는데, 좋은 테스트 코드를 통해 변경된 코드를 검증하여 문제를 해결할 수 있다.

또한, 실제 코드 변경 시 테스트 코드 역시 변경될 수 있기 때문에 테스트 코드 역시 가독성 있게 작성해야 한다.

이를 지키기 위해 아래와 같은 사항들을 준수하는 것이 좋다.

  • 1개의 테스트 함수에 대한 assert문을 최소화 한다.
  • 1개의 테스트 함수는 1가지 개념만 테스트 한다.

또한, 좋은 테스트 코드는 아래 FIRST 라는 규칙을 준수해야 한다.

  • Fast - 테스트는 빠르게 동작하며 자주 돌릴 수 있어야 한다.
  • Independent - 각 테스트는 독립적이며 서로 의존해서는 안된다.
  • Repeatable - 어느 환경에서도 반복 가능해야 한다.
  • Self-Validating - 테스트는 boolean 값으로 결과를 내어 자체적으로 검증되어야 한다.
  • Timely - 테스트하려는 실제 코드를 구현하기 직전에 구현해야 한다.

References