TDD란 용어를 let, const를 배우던 코린이(지금도 코린이지만..) 시절부터 들어왔다.
과연 무엇이길래 중요하다고 하는 것일까? 궁금해만 하다가 프로젝트 리팩토링을 하며
TDD를 적용시키기 위해 공부 해보게 되었다.
TDD란?
TDD
란 Test Driven Develpment
의 약자로 '테스트 주도 개발'
이라고 한다. 반복 테스트를 이용한 소프트웨어 방법론으로, 엔지니어 켄트 벡(Kent Beck)
에 의해 고안되었다. 작은 단위의 테스트 케이스를 작성하고 이를 통과하는 코드를 추가하는 단계를 반복하여 구현한다. 짧은 개발 주기의 반복에 의존하는 개발 프로세스이며 애자일 방법론 중 하나인 eXtream Programming(XP)의 'Test-First' 개념에 기반을 둔 단순한 설계를 중요시한다.
TDD = TFD(Test-First Development) + Refactoring
eXtream Programming(XP)란?
미래에 대한 예측을 최대한 하지 않고,
지속적으로 프로토타입을 완성하는 애자일 방법론 중 하나이다.
이 방법으론은 추가 요구사항이 생기더라도, 실시간으로 반영할 수 있다.
TDD는 왜 하는 걸까?
TDD의 바이블을 집필한 '켄트 백'은 'TDD가 단순한 설계를 장려하고 자신감을 불어넣어준다.'라고 말하였다.
일반 개발 방식
TDD 개발 방식
개발 방식 비교
두 방식의 가장 큰 차이점은 테스트 코드를 작성한 뒤에 코드개발을 진행한다는 것이다.
디자인(설계)
단계에서 프로그래밍 목적을 반드시 미리 정의하고 테스트해야할 지 미리 정의를 해야한다.
이후 테스트 코드 작성
단계에서는 위와 같은 3단계 개발 주기를 통해 테스트 코드 작성과 리팩토링 단계를 거친다.
이러한 단계가 반복적으로 진행되면서 자연스럽게 코드의 버그는 줄어들고 소스의 코드는 간결해진다. 또한 테스트 케이스 작성으로 인해 자연스럽게 설계가 개선됨으로 재설계 시간이 절감될 수 있다.
1. 높은 코드 안정성
짧은 주기의 테스트 코드 개발-리팩토링 단계를 거치며 끊임 없이 보완하고 철저한 모듈화를 통해 종속성과 의존성이 낮은 모듈로 조합된 소프트웨어 개발을 가능하게 하여 코드의 안정성을 높일 수 있다.
2. 재설계 시간의 단축
TDD는 설계 단계에서 테스트 시나리오를 작성하기 때문에 무엇을 해야하는 지 정의하고 생각할 수 있어 완성도 높은 설계로 이어진다.
이는 추후 설계가 변경되는 일을 방지할 수 있다.
3. 디버깅 시간의 단축
모듈 별로 테스트를 자동화를 하지 않는 다면 에러가 생겼을 경우 모든 레벨의 코드를 살펴봐야한다. 하지만 TDD의 경우 자동화된 단위테스트를 통해 특정 버그를 쉽게 찾을 수 있다.
=> 하지만 이러한 장점에도 불구하고 TDD를 쉽게 도입하지 못하는 여러가지 이유(단점)도 존재한다.
생산성의 저하가 가장 큰 단점이다. 한 번 개발할 코드를 2번 이상 반복하게 되어 일반적인 개발 방식보다 개발 시간이 늘어날 수 밖에 없다.
또 단순 개발이나 단발성 프로젝트의 경우 개발기간이 짧아 TDD를 적용하게 되었을 때 Ctrl + C, Ctrl + V를 통한 뻔하고 중복된 테스트 코드를 작성했을 때는 비효율적일 수 있다.
좋은 테스트 코드를 위한 'FIRST 규칙'
Fast 테스트는 빠르게 동작하여 자주 돌릴 수 있어야 한다.
만약 테스트가 느리다면 개발자는 테스트를 주저하게 되고 자주 검증하지 않은 소스코드는 그만큼 버그가 발생할 확률이 높아진다.
Independent 각각의 테스트는 독립적이며 서로 의존해서는 안된다. 테스트에 필요한 데이터는 테스트 내부에서 독립적으로 사용해야 한다. 만약 데이터가 서로에게 의존하면 테스트 하나가 실패할 때 나머지도 잇달아 실패하므로 원인을 진단하기 어려워지기 때문이다. 때론 데이터의 존재 여부를 찾는 테스트가 있는 경우엔 해당 데이터는 테스트 내부에서 생성되어야 하며 나중에 테스트에 영향을 미치지 않도록 제거해야 한다.
Repeatable 어느 환경에서도 반복 가능해야 한다. 여기서 환경은 네트워크 나 데이터베이스에 의존하지 않는 환경을 뜻한다. 결론적으로 인터넷이 되든 안 되든 데이터베이스에 접속하든 안 하든 언제 어디서나 테스트를 할 수 있어야 한다. 환경에 의존하지 않는 테스트가 실패할 수 있는 유일한 이유는 오로지 테스트할 클래스 또는 메소드가 제대로 작동하지 않기 때문이다.
Self-Validating 테스트는 성공 또는 실패로 boolean값으로 결과를 내어 자체적으로 검증되어야 한다. 테스트의 검증은 수작업이 아닌 자동화가 되어야 하는데 테스트가 실행될 때마다 메서드 출력이 올바른지를 확인하는 것은 개발자가 결정해서는 안 된다.
Timely 테스트는 적시에 즉, 테스트하려는 실제 코드를 구현하기 직전에 구현해야 한다.
결론
TDD는 Clean code that works
를 목표로 한다.
그 사실을 잊고 테스트라는 목적 그 자체만으로 TDD를 하지 말아야 겠다.
앞으로 남은 수 많은 개발자의 여정에서 Clean Code the Work
을 가슴에 품고
TDD와 함께 Refactoring 해 나가야겠다.
Reference