✅ TDD란 무엇인가?
TDD란 Test Driven Development의 약자로 '테스트 주도 개발'이라고 한다.
테스트 주도 개발(TDD)은 소프트웨어 개발 방법론 중의 하나로, 선 개발 후 테스트 방식이 아닌 선 테스트 후 개발 방식의 프로그래밍 방법을 말한다. 다시 말해 먼저 자동화된 테스트 코드를 작성한 후 테스트를 통과하기 위한 코드를 개발하는 방식의 개발 방식을 말한다.
✅ TDD를 이용한 개발방법
TDD는 기본적으로 위 3단계의 반복으로 진행하며 점진적으로 개발이 진행된다.
Red 단계에서는 실패하는 테스트 코드를 먼저 작성한다.
Green 단계에서는 테스트 코드를 성공시키기 위한 실제 코드를 작성한다.
Blue 단계에서는 중복 코드 제거, 일반화 등의 리팩토링을 수행한다.
중요한 것은 실패하는 테스트 코드를 작성할 때까지 실제 코드를 작성하지 않는 것과, 실패하는 테스트를 통과할 정도의 최소 실제 코드를 작성해야하는 것이다. 이를 통해 실제 코드에 대해 기대되는 바를 보다 명확하게 정의 함으로써 불필요한 설계를 피할 수 있고, 정확한 요구 사항에 집중할 수 있다.
✅ 일반 개발 방식과 TDD 개발 방식의 비교
🔎 일반 개발 방식
보통 개발 방식은 '요구사항 분석 -> 설계 -> 개발 -> 테스트 -> 배포'의 형태의 개발 주기를 갖는다.
하지만 이러한 방식은 소프트웨어 개발을 느리게 하는 잠재적 위험이 존재한다.
그 이유로는,
1. 소비자의 요구사항이 처음부터 명확하지 않을 수 있다.
2. 따라서 처음부터 완벽한 설계는 어렵다.
3. 자체 버그 검출 능력 저하 또는 소스코드의 품질이 저하될 수 있다.
4. 자체 테스트 비용이 증가할 수 있다.
이러한 문제점이 발생되는 이유는 어느 프로젝트든 초기 설계가 완벽하다고 말할 수 없기 때문이다. 고객의 요구사항 또는 디자인의 오류 등 많은 외부 또는 내부 조건에 의해 재설계하여 점진적으로 완벽한 설계로 나아가게 되는데, 재설계로 인해 개발자는 코드를 삽입, 수정, 삭제하는 과정에서 불필요한 코드가 남거나 중복 될 가능성이 크다.
🔎 TDD 개발 방식
TDD와 일반적인 개발 방식의 가장 큰 차이점은 테스트 코드를 작성한 뒤에 실제 코드를 작성한다는 것이다.
디자인(설계) 단계에서 프로그래밍 목적을 반드시 미리 정의해야만 하고, 무엇보다 테스트해야 할지 미리 정의(테스트 케이스 작성)해야만 한다.
- 테스트 코드를 작성하는 도중 발생하는 예외 사항(버그 및 수정사항)은 테스트 케이스에 추가하고 설계를 개선한다.
- 이후 테스트가 통과된 코드만을 코드 개발 단계에서 실제 코드로 작성한다.
이러한 반복적인 단계가 진행되면서 자연스럽게 코드의 버그가 줄어들고 소스코드는 간결해진다.
✅ TDD 예시
먼저 원하는 기능에 대한 테스트 코드를 작성한다.
import unittest
class TDDTest(unittest.TestCase):
def test_factorial(self):
self.assertEqual(120, factorial(5))
if __name__ == '__main__':
unittest.main()
그 후 실제 코드를 작성한다.
import unittest
def factorial(i):
if i > 1:
return i * factorial(i-1)
else:
return i
class TDDTest(unittest.TestCase):
def test_factorial(self):
self.assertEqual(120, factorial(5))
if __name__ == '__main__':
unittest.main()
팩토리얼 기능을 하는 함수를 구현한 후 실행을 시키면 아래와 같은 테스트 결과를 얻는다.
✅ TDD 개발 방식의 장점
🔎 디버깅 시간을 단축 할 수 있다.
이는 유닛 테스팅을 하는 이점이기도 하다.
예를 들면 사용자의 데이터가 잘못 나온다면 DB의 문제인지, 비즈니스 레이어의 문제인지 UI의 문제인지 실제 모든 레이러들을 전부 디버깅 해야하지만, TDD의 경우 자동화 된 유닛테스팅을 전재하므로 특정 버그를 손 쉽게 찾아낼 수 있다.
🔎 코드가 내 손을 벗어나기 전에 가장 빠르게 피드백 받을 수 있다.
개발 프로세스에서는 보통 ‘인수 테스트’를 한다. 이미 배치된 시스템을 대상으로 클라이언트가 의뢰한 소프트웨어가 사용자 관점에서 사용할 수 있는 수준인지 체크하는 과정이다.
이미 90% 이상 완성된 코드를 가지고 테스트하기 때문에, 문제를 발견해도, 정확하게 원인이 무엇인지 진단하기는 힘들다.
하지만 TDD를 사용하면 기능 단위로 테스트를 진행하기 때문에 코드가 모두 완성되어 프로그래머의 손을 떠나기 전에 피드백을 받는 것이 가능하다.
🔎 작성한 코드가 가지는 불안정성을 개선하여 생산성을 높일 수 있다.
앞서 말한 것처럼 TDD를 사용하면, 코드가 내 손을 떠나 사용자에게 도달하기 전에 문제가 없는지 먼저 진단 받을 수 있다. 그러므로 코드가 지닌 불안정성과 불확실성을 지속적으로 해소해준다.
🔎 재설계 시간을 단축 할 수 있다.
테스트 코드를 먼저 작성하기 때문에 개발자가 지금 무엇을 해야하는지 분명히 정의하고 개발을 시작하게 된다.
또한 테스트 시나리오를 작성하면서 다양한 예외사항에 대해 생각해볼 수 있다.
이는 개발 진행 중 소프트웨어의 전반적인 설계가 변경되는 일을 방지할 수 있다.
🔎 추가 구현이 용이하다.
개발이 완료된 소프트웨어에 어떤 기능을 추가할 때 가장 우려되는 점은 해당 기능이 기존 코드에 어떤 영향을 미칠지 알지 못한다는 것이다. 하지만 TDD의 경우 자동화된 유닛 테스팅을 전제하므로 테스트 기간을 획기적으로 단축시킬 수 있다.
✅ TDD 개발 방식의 단점
🔎 사전 준비 기간
TDD를 프로젝트에 도입하려면 사전에 필요한 지식을 습득하고 개발 환경을 구축해야 한다. TDD를 효과적으로 사용할 수 있는 수준으로 개발자를 교육하는데 보통 1~6개월간의 시간이 필요하다.
🔎 생산성 저하
프로젝트를 진행할 때 경험 때문에 어떤 예외사항이 발생할지 눈에 뻔히 보이는 경우가 종종 있는데 이러한 단발성 개발은 개발 기간이 타이트하게 잡히는 경우가 많다. 이럴 때 TDD를 이용해 테스트 코드를 작성하고 그에 통과하기 위한 코드를 작성한다면 비효율적일 것이다. TDD 방식의 개발은 일반적인 개발 방식에 비해 대략 10 ~ 30% 정도로 늘어난다.
TDD는 비용적인 측면을 고민해야 한다. 테스트 코드를 짜는 것 또한 엄연한 개발이다. 그만큼 시간을 투자함에 따라 이익을 얻어야 하는데 테스트에만 너무 과도하게 몰입해버린다면 시간 낭비가 될 것이다. 결론적으로 적당한 TDD는 개발에 있어 능률 상승을 가져올 수 있으나, 과도한 테스트는 오히려 해로울 수 있다.
📚 Reference
'Computer Science' 카테고리의 다른 글
[DB] 데이터베이스 정규화란? (0) | 2023.02.02 |
---|---|
애자일(Agile)이란? (0) | 2023.02.01 |
[DB] 데이터베이스 인덱스(Index)란 무엇인가? (0) | 2023.01.30 |
[python] 클린코드와 코드 리팩토링 (2) | 2023.01.25 |
NoSQL이랑 RDBMS의 특징과 차이점 (0) | 2023.01.21 |