테스트 주도 개발Test Driven Development(TDD)란?
켄트 벡이 창시한 개발 방법론으로 테스트부터 작성하는 개발 방법론이다. 먼저 통과하지 못할 테스트를 작성하고 테스트를 통과하도록 코드를 작성한다. 그 뒤 코드를 개선, 리팩터링하고 테스트하는 과정을 반복하는 식이다. 리팩터링 책으로 유명한 마틴 파울러가 추천하는 개발방식이다.
TDD의 가장 큰 특징은?
테스트 주도란 명칭처럼 테스트부터 작성한다! 기능부터 작성 → 테스트가 아니라, 테스트 → 기능 코드 작성이다.
파이썬을 예를 들면 테스트부터 작성한다.
def test_sum()
assert sum(1, 2) == 3
당연히 sum 함수 구현이 안 되어 있으니 테스트는 실패한다. 위 테스트가 성공할 때까지 sum함수를 구현하는 식이다.
TDD로 개발한다면 코드만큼 테스트가 늘어나게 된다. 테스트 자동화 툴을 통해서 기능을 추가할 때마다 개별 및 전체 테스트를 해가면서 개발한다.
기능부터 개발
대부분 개발자들은 기능부터 개발한다. 테스트 작성은 시간이 나면 그때서야 하거나 아예 작성하지 않는 경우도 많다. 그렇다면 어떻게 확인할까? 테스트를 작성하지 않았으므로 웹 개발이면 화면을 통해서, API서버 개발이라면 Postman같은 툴을 활용해서 API 실행해서 그때 그때 확인한다.
기능 개발부터 하는 것이 처음에는 빠르다
처음에는 테스트 없이 개발하는 게 빠르다. 테스트 작성할 시간을 아낄 수 있으니까. 하지만 코드량이 늘어날수록 복잡도가 증가할수록 느려진다. 복잡도가 증가할수록 의존성이 높아진다. 그래서 기능을 하나 추가할 때 테스트할 범위가 늘어난다. 미리 작성된 테스트 코드를 실행하는 게 아니라 일일이 Postman 같은 툴로 테스트를 매번 실행하는 경우를 생각해보자. 이렇게 실행한다고 오류를 다 잡아낼 수도 없다. 점점 버그가 늘어나고 디버깅 시간도 급격히 늘어난다. 혼자 개발하면 오류 예상 지점을 알기 때문에 쉽게 찾지만 여러 명이 함께 개발한다면 오류가 왜 발생하는지 찾기가 어렵다. 찾아서 오류를 수정해도, 다시 또 다른데서 오류가 터질지 알 수 없다.
소프트웨어 개발은 집짓기와 비슷하다
건축학을 뜻하는 아키텍처architecture란 용어를 소프트웨어 개발에서도 그대로 쓸 정도로 말이다. 개별 함수, 클래스가 집짓기로 비유하면 벽돌 같은 건축자재가 된다. 테스트 없는 개발은 품질 인증 없는 벽돌과 시멘트, 철근 등으로 감리없이 집을 짓고 있는 것과 마찬가지다.
소프트웨어는 계속 바뀐다
부드러운 소프트웨어라 함수나 클래스는 언제든 모양이 바뀐다. 이게 가장 큰 문제다. 요구사항에 따라 기능이 추가, 수정, 삭제되는 등 계속 바뀐다. 사각형이었던 벽돌이 동그란 모양으로 바뀐다면 순식간에 집이 무너질 수밖에 없다. 소프트웨어에서는 장애로 나타난다.
테스트는 화재경보기
소프트웨어가 아파트 같은 집합건물이라면 개별 함수나 클래스는 방에 비유할 수 있다. 테스트는 화재경보기 역할을 한다. 개별 함수 또는 클래스가 오류가 있다는 것을 바로 알려주기 때문이다. 굳이 디버깅에 긴 시간을 들이지 않아도 된다. TDD로 개발팀 전체가 개발했다면 내가 수정한 코드와 전혀 관계 없다고 생각한 곳에서 발생하는 오류도 개발 과정에서 테스트 실행만으로 바로 알게 된다. 운영 중 장애 발생 가능성이 줄어든다.
테스트 코드 없는 리팩터링은 불가능하다
어디서 문제가 터질지 알 수 없기 때문이다. 그래서 리팩터링 책을 쓴 마틴 파울러가 TDD를 추천한 것이다. 아무런 기능 변경도 없는 코드 개선을 위한 리팩터링을 해서 개발팀이 장애를 일으킨다면 운영팀이나 CEO가 뭐라고 할지 상상해보자. 쓸데 없는 짓 하지 말라는 이야기 듣기 딱 좋다. 더 나은 코드로 개선하려면 테스트가 반드시 필요하다. 하지만 처음부터 작성하지 않은 테스트를 한꺼번에 작성하기란 힘들다. 결국 레거시legacy라 불리는 유산이 쌓여갈 수밖에 없다.
TDD는 정말 좋지만 익숙해지기 쉽지 않다
익숙하지 않다. 세살 버릇 여든 간다고 기능 개발부터 하던 버릇을 쉽게 고치기 쉽지 않다. 익숙하지 않기 때문에 처음에 오래 걸리지만, 'TDD란 방법론이 오래 걸릴 수 밖에 없구나.'라고 생각하기 쉽다. TDD를 시도하다가도 개발 일정이 촉박하다면 포기하게 된다. 특히 테스트 코드를 필수로 생각하지 않는 개발팀에 소속되어 있다면 말이다.
TDD를 꼭 해보기
간단한 프로젝트부터 TDD를 적용해보자. TDD를 직접 해보면 왜 TDD를 유명 개발자들이 추천하는지 알게 된다. 진짜 TDD가 더 빠르고 효과적이다. 이 때 주의할 점은 앞의 예에서 설명했듯이 테스트부터 작성해야 한다. 내 경우도 htmltomd란 간단한 오픈소스를 만들 때 TDD로 처음부터 작업했는데 훨씬 쉽게 오류를 찾고 리팩터링 할 수 있었다. 특히 테스트 코드가 충분하니 과감하게 변경을 시도할 수 있었다.
CTO나 개발팀장이라면 TDD를 기본값으로
내가 CTO나 개발팀장이라면 TDD를 기본값으로 만들 거 같다. 깃허브 액션을 이용해 풀 리퀘스트(PR)에 전체 테스트를 자동화한다. 전체 테스트를 통과 못하거나 필수 테스트 코드가 없다면 코드 리뷰 자체를 안 하는 식으로 개발 정책을 만들 거 같다. 그리고 코드 리뷰 때는 기능 개발 코드는 보지도 않고 테스트 코드가 충분한지부터 볼 거 같다. 코드를 눈으로 확인해서는 제대로 작동하는지는 쉽게 알 수 없지만, 테스트는 실제 작동 결과를 확인하기가 무척 쉽기 때문이다.
TDD 없는 애자일Agile이 가능할까
TDD를 만든 켄트 벡이 바로 익스트림 프로그래밍도 개발했고, 애자일Agile 선언문에 참여했다. TDD 없이 애자일이 가능할까. 애자일은 그때 그때 계획이 변경되는 것을 빠르게 수용해야 한다. 코드에 큰 폭의 변화가 빈번하게 이뤄지는데 테스트 없이 가능할까. 많은 스타트업에서 애자일이 제대로 작동하지 않는 이유 중 하나는 TDD 없이 애자일만 도입하려고 하기 때문일지도 모르겠다.