프로그램 아키텍쳐/소프트웨어공학

테스트의 필요성과 테스트 주도 개발(TDD, Test Driven Development)

본클라쓰 2011. 3. 15. 13:34

'토비의 스프링 3' 책을 읽으면서 개발시 부딛혔던 수 많은 문제에 대해 개념적인 정리가 되는 느낌이다. 여기서 테스트 코드에 대한 생각을 엿 볼 수 있는데 가지고 있던 생각과 비교해 고쳐야 할 부분에 대해 생각해보게 되었다.

 

 

테스트 코드의 필요성

 

개인적으로 테스트 코드를 작성하여 프로그램이 정상으로 동작하면 테스트 코드를 모두 삭제하였다. 또한 테스트 단위를 단위 테스트가 아닌 기능 테스트에 초점을 맞춰 진행해 테스트에 걸리는 시간도 상당히 오려걸렸다. 하지만 이런 생각은 잘못된 것이었다.

 

토비의 책을 발췌해 보며, "개발자들이 낭망이라고 생각하는 '눈물 젖은 커피와 함께 며칡간 밤샘을 하며 오류를 잡으려고 애쓰다 전혀 생각치도 못했던 곳에서 간신히 찾아낸 작은 버그 하나의 추억'이라는 건, 사실 '진작에 충분한 테스트를 했었다면 쉽게 찾아낼 것을 미루고 미루다 결국 커다란 삽질로 만들어버린 어리석은 기억'일 뿐이다." 라는 말로 압축된다.

 

테스트란 코드가 정확히 동작하는지를 확인해서 작성한 코드를 확신할 수 있게 해주는 작업이다.

 

또한 테스트의 결과가 원하는 대로 나오지 않는 경우에는 코드나 설계에 결함이 있음을 알 수 있고, 이를 통해 코드의 결함을 제거해 가는 작업, 일명 디버깅을 거치게 되고, 최종적으로 테스트가 성공하면 모든 결함이 제거되었다는 확신을 얻을 수 있다.

 

이런 테스트는 테스트하고자 하는 대상에만 집중해서 테스트하는 것이 바람직하다. 한꺼번에 너무 많은 것을 몰아서 테스트하면 테스트 수행 과정도 복잡해지고, 오류가 발생했을 때 정확한 원인을 찾기가 힘들어진다. 관심사의 분리라는 원리가 여기에서도 적용된다.

 

테스트의 관심이 다르다면 테스트 할 대상을 분리하고 집중해서 접근해야 한다. 이와 같이 작은 단위로 제한해서 테스트하는 것이 편리하다. 단위 테스트는 주로 개발자가 만든 코드를 스스로 확인하기 위해 사용하는데, 그래서 이를 개발자 테스트 또는 프로그래머 테스트라 한다.

 

고객이 테스트를 하는 시점이면 이미 개발자가 코드를 작성하고 나서 한참 뒤일 것이다. 그때서야 오류가 처음 발견되고 개발자에게 문제가 통보된다면 개발자는 오래 전에 만든 코드를 뒤져서 버그를 수정해야 한다.

 

이런 경우와 코드를 만들자마다 빠르게 테스트해서 오류가 발견했을 때 버그를 수정하는 경우를 비교해 보면 개발자 입장에서 어떤 경우가 더 빠르고 쉽게 문제의 원인을 찾고 수정이 가능할까? 혹시 테스트를 만들고 자주 실행하면 개발이 지연되지 않을가 염려할 지도 모르겠다.

 

하지만 그렇지 않다. 테스트는 어플리케이션 코드보다 상대적으로 작성하기 쉬운데다 각 테스트가 독립적이기 때문에 코드에 양에 비해 작성하는 시간이 얼마 걸리지 않는다. 게다가 테스트 덕분에 오류를 빨리 잡아낼 수 있어서 전체적인 개발 속도는 오히려 빨라진다. 테스트 코드를 만들지 않아도 언제가는 웹 화면을 통해 테스트를 하게 되니깐!

 

xUnit 프레임워크를 만든 켄트 백은 "테스트란 개발자가 마음 편하게 잠자리에 들 수 있게 해주는 것"이라고 했다. 지저분한 코드를 정리한다고 조금 손을 댔는데, 이것 때문에 혹시 기존 기능에 문제가 생기진 않을까?라는 불안한 마음으로 퇴근한 경험이 개발자라면 한 두 번쯤 있을 것이다. 또한 새로운 기능을 추가하고 적용하고 왔는데, 갑자기 회사에서 연락이 와서 그 기능 적용 이후로 다른 부분에서 많은 문제가 생겼으니 당장 해결해달라는 긴급 요청을 할 때도 있다.

 

나는 셀 수도 없이 그런 경험을 많이 했다. 모처럼 친구들을 만나고 즐거운 시간을 보내고 있을 대나 휴가로 여행을 떠나서도 종종 며칠 전에 손을 댔던 코드 때문에 어떤 문제가 생겼다고 연락이 오지 않을가 하는 불안감이 마음에서 떠나지 않을 때도 있었다.

 

 

이처럼 책에서 정리된 테스트의 필요성은 테스트 코드를 지우는 나의 행동이 옳지 못하다고 말하는 것 같다. 테스트 또한 하나의 프로그래밍이라는 생각의 전환이 필요하다. 테스트를 실시간으로 주기적으로 할 수 있는 방법을 찾는 것이 프로그래밍 기술을 향상시키는 방법인 것이다.

 

 

 

테스트 주도 개발

 

만들고자 하는 기능의 내용을 담고 있으면서 만들어진 코드를 검증도 해줄 수 있도록 테스트 코드를 먼저 만들고, 테스트를 성공하게 해주는 코드를 작성하는 방식이 테스트 주도 개발(test driven development, TDD)라 한다. 테스트 주도 개발은 개발자가 테스트를 만들어가며 개발하는 방법이 주는 장점을 극대화 한 방법이라고 볼 수 있다. "실패한 테스트를 성공시키기 위한 목적이 아닌 코드는 만들지 않는다"는 테스트 주도 개발의 기본 원칙이다.

 

테스트를 이용하면 새로운 기능도 기대한 대로 동작하는지 확인할 수 있을 뿐 아니라, 기존에 만들어 뒀던 기능들이 새로운 기능을 추가하느라 수정한 코드에 영향을 받지 않고 여전히 잘 동작하는지를 확인할 수도 있다.

 

이런 테스트는 자동으로 수행되게 하면 좋은데, 자동으로 수행되는 테스트의 장점은 자주 반복할 수 있다는 것이다. 번거로운 작업이 없고 테스트를 빠르게 실행할 수 있기 때문에 언제든 코드를 수정하고 나서 테스트를 해 볼 수 있다. 때로는 단 한 줄의 코드를 건드렸는데 전체 기능에 영향을 주기도 한다. 개발이 완료 될 즘 또는 개발을 일단 완료하고 실전에서 운영 중인 상황에서 코드를 수정하려고 한다면 아무리 간단한 수정이라고 하더라도 이게 그럭저럭 돌아가는 전체 어플리케이션에 심각한 문제를 일으키지는 않을까 하는 두려움이 앞선다.

 

그럴 때 만들어둔 기능에 대한 테스트가 있다면 수정 후 빠르게 전체 테스트를 수행해서 수정 때문에 다른 기능에 문제가 발생하지 않는지 재빠릴 확인하고, 성공한다면 마음에 확인을 얻을 수 있다.

 

테스트 코드는 마치 잘 정의된 하나의 기능 정의서처럼 보인다. 그래서 보통 기능 설계, 구현, 테스트라는 일반적인 개발 흐름의 기능 설계에 해당하는 부분을 이 테스트 코드가 일부분 담당하고 있다고 볼 수도 있다. 이런 식으로 추가하고 싶은 기능을 일반 언어가 아니라 테스트 코드로 표현해서, 마치 코드로 된 설계 문서처러 만들어 놓은 것이라고 생각해야 한다.

 

앞으로는 항상 테스트 코드를 남겨두고 코드에 변경이 되어야 할 경우 테스트 코드를 변경한 후 실제 코드에 변경하는 방법으로 프로그래밍 스타일을 변경해야 겠다.

 

 

 

출처) 토비의 스프링 3