TDD ( 테스트 주도 개발 ) 란 ?

TDD ( Test Driven Development )

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

제품이 오류 없이 정상 작동하는지 확인하기 위해 모든 코드는 프로그래머가 작성하고 나서 테스트를 거치게 되는데,

TDD에서는 제품의 기능 구현을 위한 코드와 별개로, 해당 기능이 정상적으로 움직이는지 검증하기 위한 테스트 코드를 작성합니다.

이를 통해 테스트가 실패할 경우, 테스트를 통과하기 위한 최소한으로 코드를 개선하고, 최종적으로 테스트에 성공한 코드를 리팩토링 하는 과정을 거칩니다.

 

TDD 개발 절차

테스트 주도 개발은 다음과 같은 개발 절차를 가집니다.

  • RED ( Write a failing test ) : 실패하는 테스트 코드를 먼저 작성합니다.
  • GREEN ( Make the test pass ): 테스트 코드를 성공시키기 위한 실제 코드를 작성합니다.
  • BLUE ( Refactor ) : 중복 코드 제거, 테스트 통과 유지 등의 리팩토링을 수행합니다.

 

 

코드 중심의 개발과 테스트 주도 개발의 차이점

가장 큰 차이점으로는 "코드 중심 개발"코드 개발을 하고 테스트를 하는 반면, "테스트 주도 개발"테스트 코드를 작성하고 코드 개발을 하는 것입니다.

 

  • 코드 중심 개발

코드 중심 개발은 테스트하기도 전에 코드를 다 개발하고 마지막에 테스트를 거치므로, 마지막 단계인 테스트가 실패하면

다시 처음부터 설계하고 다시 코드 개발을 하고 테스트를 하는 비효율적이고 테스트 비용이 증가할 수 도 있습니다.

왜냐하면 세상에 어떤 것이든 처음 부터 완벽한 것은 없기 때문입니다.

또한, 고객의 요구사항이 추가 된다거나 오류 등으로 재설계를 할때 코드를 삽입, 수정, 삭제하는 과정에서 불필요한 코드가 남거나 중복이 될 위험성도 존재합니다.

 

 

  • 테스트 주도 개발

1. 설계 단계에서 프로그래밍 목적을 반드시 미리 정의하고, 테스트해야할 테스트 케이스를 작성해야합니다.

2. 테스트 코드단계에서 테스트 코드를 작성하는 도중 오류나 수정할 부분이 생기면 테스트 케이스에 추가하고 다시 설계개선합니다.

3. 마지막으로 테스트가 통과된 코드만을 코드 개발 단계에서 실제 코드로 작성합니다.

 

TDD 과정을 PPT 발표 자료 만드는 과정과 비교하면,

( 목차구성 = 테스트 코드 작성 ), ( 초안작성 = 코드 개발 ), ( 수정하기 = 코드 수정 ) 으로 비교할 수 있습니다.

만든 자료를 반복적으로 확인하고 수정하면 좋은 발표자료가 되는 것처럼 TDD를 통해 고품질의 소프트웨어를 만들 수 있습니다.

 

즉, 테스트 주도 개발 방식을 통해 반복적으로 코드를 테스트하며 코드의 오류를 줄이고 소스코드를 더욱 간결하게 만들수 있으며

테스트 케이스 작성으로 인해 자연스럽게 설계가 개선됨으로써 재설계 시간이 절감됩니다.

 


TDD의 장단점

 

장점

 

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

TDD는 코드의 재사용 보장을 명시하므로 TDD를 통한 소프트웨어 개발 시 기능별 철저한 모듈화가 이뤄집니다.

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

 

  • 추가 구현의 용의함

개발이 완료된 소프트웨어에 어떤 기능을 추가할 때 가장 우려되는 점은 해당 기능이 기존 코드에 어떤 영향을 미칠지 알지 못합니다.

하지만 TDD의 경우 자동화된 유닛 테스팅을 전제하므로 테스트 기간을 획기적으로 단축시킬 수 있다.

 

  • 높은 코드 안정성

짧은 주기의 테스트 코드 개발-리팩토링 단계를 거치며 끊임 없이 보완하고 철저한 모듈화를 통해 종속성과 의존성이 낮은 모듈로 조합된 소프트웨어 개발을 가능하게 하여 코드의 안정성을 높일 수 있다.

 

  • 재설계 시간의 단축

TDD는 설계 단계에서 테스트 코드를 먼저 작성하기 때문에 무엇을 해야하는 지 정의하고 생각할 수 있어 완성도 높은 설계로 이어집니다.
개발 진행 중 소프트웨어의 전반적인 설계가 변경되는 일을 방지할 수 있습니다.

 

  • 디버깅 시간의 단축

모듈 별로 테스트를 자동화를 하지 않는다면 에러가 생겼을 경우 모든 레벨의 코드를 살펴봐야합니다.

하지만 TDD의 경우 자동화 된 유닛 테스팅을 전제하므로 특정 버그를 손 쉰게 찾아낼 수 있습니다.

 

 

TDD가 이러한 많은 장점을 가지고 있음에도 모든 개발자들이 이 TDD를 따르는 것은 아닙니다. 그 이유는 아래와 같습니다.

 

단점

 

  • 기존 방식에 적응 되어 버려 개발 방식을 바꾸기 어려움

이미 기존 코드 중심 개발으로 오랜 시간 개발을 해온 개발자들은 기존과 다른 방식인 TDD로 개발 방식을 바꾸긴 어려울 것입니다.

하지만 오히려 개발을 별로 해보진 않은 신입 개발자들은 적용하기 쉬울 것 입니다.

 

  • 생산성 저하

한 번 개발할 코드를 처음부터 2개의 코드를 짜야하고 중간중간 테스트를 하면서 고쳐나가야하기 때문에 일반적인 개발 방식보다 개발 시간이 늘어날 수 밖에 없습니다.

TDD 개발 방식은 일반적인 개발 방식에 비해 시간이 대략 10 ~ 30% 정도 늘어난다고 합니다.

SI 프로젝트에서는 소프트웨어 품질보다는 납기일 준수가 중요해 TDD 방식을 잘 사용하지 않습니다.

또 단순 개발이나 소규모 프로젝트의 경우 개발기간이 짧아 TDD를 적용하게 되었을 때 Ctrl + C, Ctrl + V를 통한 뻔하고 중복된 테스트 코드를 작성했을 때는 비효율적일 수 있습니다.

 

 

 

 


테스트 종류

인수 테스트

클라이언트 입장에서 시스템이 제공하는 기능이 올바르게 동작하는지 확인합니다.

  • 모든 구성요소를 하나로 엮어서 사용자의 관점에서 테스트한다.
  • Java에서는 RestAssured, MockMvc 같은 도구를 활용하여 인수 테스트를 작성할 수 있다.
  • 예시 : ) 회원가입 기능이 올바르게 작동하는지 확인

 

컴포넌트 테스트 ( Widget test )

하나의 컴포넌트 또는 위젯을 테스트 하는 것으로 UI를 테스트 하는 것에 속합니다.

해당 테스트는 위젯의 UI가 예상대로 보이고 상호작용을 확인하는 것을 목표로 합니다.

 

통합 테스트 ( Integration test )

완전한 응용 프로그램을 통합적으로 테스트합니다.

시스템의 각 구성요소들이 함께 올바르게 연동되는지 확인합니다.

  • 개발자가 변경할 수 없는 부분(ex. 외부 라이브러리)까지 묶어서 검증
  • DB 접근 등 전체 코드와 다양한 환경이 제대로 작동하는지 확인하는데 필요한 모든 작업 수행
  • 실제 환경에서 발생하는 버그까지는 확인할 수 없음
  • 스프링 부트에서는 클래스 상단에 @SpringBootTest 어노테이션을 붙여 통합 테스트를 수행할 수 있다.
  • 예시 : ) 서버의 회원가입 코드를 직접 테스트

 

단위 테스트 ( Unit test )

컴퓨터 프로그래밍에서 소스 코드의 특정 모듈이 의도된 대로 정확히 작동하는지 검증합니다.

단일 함수 또는 클래스를 테스트 하는 것으로 코드의 논리 단위의 정확성을 확인합니다.

  • 클래스 or 메서드 수준으로 대상 단위를 작게 설정해 ( 기능을 분리 ) 테스트
  • Java는 주로 JUnit으로 테스트한다

 


좋은 테스트 코드를 위한 규칙

테스트를 작성할 때는 FIRST와 Right - BICEP이라는 키워드를 기억해둡시다.

FIRST
  • ast: 목표한 기능을 빠르게 검증할 수 있어야 합니다.
  • ndependent: 테스트의 단위는 다른 테스트와 독립적이어야 합니다. 순수하게 목표한 기능만 테스트합니다.
  • epeatable: 반복적으로 테스트를 수행해도 동일한 결과를 얻을 수 있어야 합니다.
  • elf-validating: 스스로 검증할 수 있어야 합니다.
  • imely: 실시간으로 검증할 수 있어야 합니다.

 

Right-BICEP
  • : 결과가 올바른지 판단할 수 있어야 합니다.
  • oundary: 모든 경계(Boundary) 조건이 일치해야 합니다.
  • nverse: 역(Inverse) 관계를 확인할 수 있어야 합니다.
  • ross-check: 다른 수단을 사용하여 결과를 교차 확인(Cross-check) 할 수 있어야 합니다.
  • rror condition: 에러 조건(Error condition)을 강제로 만들 수 있어야 합니다.
  • erformance: 성능(Performance) 특성이 한도 내에 있어야 합니다.

 


참고자료
https://velog.io/@ryan-son/%ED%85%8C%EC%8A%A4%ED%8A%B8-%EC%A3%BC%EB%8F%84-%EA%B0%9C%EB%B0%9C-Test-Driven-Development-TDD
https://runa-nam.tistory.com/121
https://velog.io/@wngud4950/TDD%EB%9E%80

https://hanamon.kr/tdd%EB%9E%80-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EC%A3%BC%EB%8F%84-%EA%B0%9C%EB%B0%9C/