태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.

티스토리 툴바



소개

TDD(Test Driven Development) Tutorial

  • author - 박응용
  • date - 2003/04/25

오랜 경험이 있는 프로그래머라도 TDD에 대한 얘기를 들어보지 못한 사람들이 많다. 언젠가 한번은 들어본적이 있겠지만 그냥 무심코 지나쳐 버렸을 것이다. 정보화 시대에 홍수처럼 쏟아지는 정보들의 틈바구니 속에서 그냥 그런 정보로 흘려지나가 버렸을 것이다.

본인이 강조하고 싶은 것은 TDD는 유행이 아니라는 것이다.

자바나 C 또는 파이썬 같은 언어들마저도 한시대의 유행처럼 되어 버릴 수 있겠지만 TDD는 그렇지 않다. 왜냐하면 TDD는 프로그래밍 언어들 사이에서 살아 숨쉬는 것이기 때문이다.

즉, 내공이라 할 만하다. 진정한 실력말이다. 진정으로 프로페셔널한 프로그래머가 되고자 한다면 TDD에 관심을 가져야만 한다.

아니 적어도 이 책에서 말하는 내용만이라도 한번쯤 귀 기울여보길 바란다. 당신에게 어떤 변화가 있을지 모를 일 아닌가?

TDD란 무엇인가?

TDD는 몰라도 XP(Extream Programming)에 대해서 들어본 사람은 많을 것이다.

XP는 프로젝트의 혁명적인 새로운 시각을 보여준다. 하나의 프로젝트를 진행해 나가는 모든 과정이 매우 신선하고 충격적이다. XP에 관한 보다 자세한 사항은 다음의 사이트를 참고하도록 하자.

본인은 프로그래머이기에 XP관련 서적을 읽으며 TDD에 관심을 갖게 되었다. TDD는 간단하게 말해서 코딩을 해나가는 절대적인 방법이라 할 만하다.

모든 테스트를 100%통과하는 코드, 스트레스가 없는 코드, 언제든지 수정이 용이한 코드, 상호 의사소통이 가능한 코드.

어떠한가?

테스트란 무엇인가?

Test란 무엇인가?

대부분의 많은 프로젝트는 프로젝트가 종료되는 시점에 테스트를 행한다. 그것도 마감일이 얼마남지 않은 빠듯한 시점에서 말이다. 그런식의 테스트는 완전하지도 않고, 불안하기 짝이 없다.

그리고 테스트가 끝난후에 시스템을 오픈한 후, 문제점이 발생하면 기존에 했던 테스트를 기억할 수도 없고, 믿을 수도 없기에 또다시 한번 거쳤던 테스트를 다시 해야만 한다.

TDD프로그래머는 이러한 테스트 방식을 싫어한다.

아주 작은 단위의 실제코드가 만들어지는 시점에 테스트는 되어야 하고, 통과되어야만 한다. (TDD는 실제코드 이전에 테스트 코드가 존재해야 한다.) 이런 작은 단위의 코드들이 점차로 증가 한다고 가정해 보자. 각각의 작은 단위의 코드들은 충분한 테스트를 거친 것이므로 적어도 믿을만한 것들이다. 문제가 발생한다면 새로이 추가된 부분 New Code에서 문제가 발생할 확률이 높은 것이다.

디버깅하기가 쉽지 않겠는가? 단지 새로운 부분에 대한 테스트를 좀 더 보강하면 될것이다.

테스트는 프로그래머에게 확신을 준다.

때때로 프로그래머는 자신이 작성한 코드가 어떻게 동작하는지 명확히 알 지 못할때가 있다. 자신이 알지 못하는 무언가에 의해서 프로그램이 정상적으로 동작하는 경우를 말한다.

이런 불명확함을 남겨 놓고 계속 코딩을 진행해 나간다면 불행을 키우는 일이 될 것이다. 시스템이 계속해서 발전할수록 숨어 있는 불명확함은 그 정체를 더욱더 꽁꽁 숨겨놓을 테니까 말이다.

TDD 프로그래머는 불명확함을 명확함으로 밝혀내는 힘을 가져야 한다. 그것의 원동력은 역시 테스트이다. 불명확함을 테스트 코드로 명확함으로 바꾸는 것이다.

TDD와 테스트

See also : http://c2.com/cgi/wiki?TestDrivenDevelopment

What is Tdd ?

그렇다면 TDD의 실체에 대해서 생각해 보도록 하자.

TDD는 자바 랭귀지를 배우거나 Xmlrpc등의 개념을 배우는 것과는 매우 다르다. 지식 기반이 아니라 경험에서 우러나오는 것이기 때문이다.

xmlrpc의 개념에 대해서 알게 되면 그것을 바로 써먹을 수 있지만 TDD는 사뭇 다르다. TDD가 무엇을 하는것인지 알게 되어도 능숙해지려면 꽤나 시간이 걸리기 때문이다.

무협지를 보라. 내공이 하루아침에 쌓이는 경우가 있는가?

TestDrivenDevelopment

대부분의 프로그래머가 가지고 있는 코딩 습관에 대해서 먼저 언급해 보자.

일단 구현해야 할 대상이 생긴다면 프로그래머는 자신의 노하우를 이용하여 최상의 프로그램을 만들어 낸다. 그리고 자신이 만든 코드가 제대로 동작하는지 테스트를 한다. 이것이 우리가 늘 사용해 왔던 일반적인 방법이다.

하지만 TDD는 이러한 순서를 완전히 뒤짚는다. 테스트를 먼저하고 코딩을 한다. 이것이 도대체 말이 되는 얘기인가? 실제코드가 없는데 어떻게 테스트를 하겠는가? 당연한 의문이다. 하지만 우습게도 TDD를 하는 모든 사람들은 테스트를 먼저하고 코딩을 한다. 테스트를 한다는 의미는 테스트 코드를 작성한다는 말이다.

테스트 코드를 먼저작성하고 그 테스트 코드를 통과하는 실제 코드를 단계적으로 만들어가면서 코딩을 하는 것이 바로 TDD이다.

테스트를 먼저하는 것과 나중에 하는것에는 엄연한 차이가 있다. 테스트를 나중에 하는 것은 코드 종속적인 성향이 강하고, 테스트를 먼저 하는 것은 자신의 의도대로 코드가 만들어 지길 기대한다는 능동적인 느낌이다.

능동적인 코딩과 피동적인 코딩.

이것은 매우 큰 차이이다.

TestDrivenDevelopment는 초기에 Test First Programming으로 불리웠다. 테스트를 먼저 한다는 의미가 강한 말이다. 하지만 이보다 Test Driven이라는 표현이 훨씬 적합한 말이다. Test 주도적으로 실제코드가 만들어지기 때문이다.

간단한예

간단한 예를 들어보자.

만약에 구구단 프로그램을 만든다면 TDD 프로그래머는 다음과 같이 시작할 것이다. (아래의 예는 파이썬으로 작성되었으나 파이썬 언어를 몰라도 무슨내용인지 알 수 있을것이다.)

two = GuGu(2)
self.assertEquals(2*3, two.get(3))
위의 코드가 바로 테스트 코드이다. 의도는 다음과 같다.

GuGu라는 클래스는 구구단 클래스이다. 생성자에 몇단인지를 알려주고 get이라는 메써드를 통해 해당 단의 값을 리턴하게 된다. 위의 예처럼 2단 객체를 만들고 get(3)로 two.get(3)의 값이 2*3이 되는지를 확인하는 것이다.

물론 이러한 테스트 코드를 작성하는 순간 GuGu라는 클래스는 존재하지 않는다. 그냥 테스트 코드에 적힌 상상속의 클래스이다. 이 테스트 코드를 통과하기 위해서는 먼저 GuGu라는 클래스를 만들어야 할 것이고 그에 해당되는 메써드들을 만들어야 할 것이다.

위와 같은 테스트 코드를 통과하기 위해서는 아래와 같은 코드가 자연스럽게 생기게 된다.

class GuGu:
    def __init__(self, num):
        self.num = num

    def get(self, which):
        return self.num * which

물론 위처럼 테스트를 작성하고 실제코드를 작성하는것이 TDD의 전부는 아니다. 실은 아주 작은 부분이다. 일단 테스트를 만들고 테스트를 통과하기 위한 실제코드를 빠르게 작성하는 것이 주 목표이지만, 이렇게 작성된 실제 코드를 리팩토링하고 알맞는 메타포를 찾아내는 것들이 더욱 중요하다 하겠다.

보통 리팩토링 과정과 어떤 테스트를 수행해야 할지 결정해야 하는 시간이 가장 오래걸린다고 할 수 있겠다.

테스트코드 없이는 단 한줄도 코딩을 하지 않는다

TDD 초보자가 제일 처음에 겪는 어려움은 도대체 어떻게 테스트 코드를 만들것인가? 하는 점이다. 자신이 만들 실제 코드의 동작을 적절히 테스트할 수 있는 코드가 없이는 단 한줄도 실제코드를 작성하지 말라는 말이 있다.

하지만 이것은 테스트 코드의 중요성을 강조하기 위한 말임을 상기하면 될것이다. 자신이 실제 코드를 적절하고 효율적으로 테스팅 하고 있다고 믿는다면 아마도 당신의 생각이 맞을 것이다.

(개인적으로 절대적인 테스트 코딩의 룰은 없다고 생각한다. 실제 코드가 내가 원하는 대로 테스트 되고 있다면 그만 아니겠는가?)

TDD전문가들은 말한다. 어떤 코드도 테스트를 선행으로 작성할 수 있다. 그렇다, 맞는 말이다. 하지만 우리 TDD초보자들은 이 말에 너무 신경쓰지 말도록 하자. 언젠가는 우리도 그러한 경지에 오를 수 있다. 하지만 지금은 아니다.

모든것을 TDD로 해나가기에 어려운 것이 몇가지 있는데, 대표적인 것으로 네트워크, 웹, 데이터베이스 관련 프로그램이다. 한마디로 얘기하면 독립적인 프로그램이 아니라 다른 어떠한 것에 의존적으로 동작하는 프로그램을 작성할 때 TDD는 꽤 어렵다. (이런경우 Mock Object를 사용하기도 하고 실제 통신을 하여 테스트하기도 한다. 상황에 맞게끔 어떻게 테스트 코드를 만들것인가는 각자의 능력이다.)

하지만 보다 중요한 것은 실제 코드를 필요한곳에 정확하고 적절하게 테스팅하는 방법임을 명심하도록 하자.

항상 100% 테스트를 통과해야 한다

작성한 테스트 코드가 실패함에도 불구하고 다른 테스트 코드를 작성한다던가 테스트 코드 작성중 실제 코드의 어떠한 부분이 잘못되었다는게 상기되어 실제 코드를 재작성하는 오류를 범하지 않기 바란다.

이런식으로 코드를 만들다보면 스파게티 소스가 되기 쉽상이다.

이미 하나의 테스트가 잘못되었다면 그것 먼저 통과하도록 힘써야 할 것이다. 때론 테스트의 범위가 너무 커서 실제 코드를 어렵게 작성해야 하는 경우도 생긴다. 이때쯤에는 뭔가 잘못되었음을 느낄 수 있어야 한다. 테스트를 작성하고 그 테스트를 통과하기 위한 방법이 쉽게 떠오르지 않는다면 테스트에 문제가 있는 것이다.

테스트가 너무 큰 범위의 코드를 상대한다면 테스트를 잘게잘게 나누어 보라. 분명 쉬운 길이 있게 마련이다. 당신은 물론 똑똑하지만, divide and conquer가 당신을 더욱 영리하게 할 것이다.

TDD의 흐름

TDD에 절대적인 방법이 있는것은 아니지만, 일반적인 흐름이라는 것이 있다. 그 흐름은 다음과 같다.

1. 무엇을 테스트할 것인가 생각한다. 
2. 테스트를 작성한다.
3. 테스트가 실패하게 만든다. 
3. 테스트를 통과하는 코드를 작성한다.
4. 코드를 리펙토링한다. (리펙토링 과정에서 물론 테스트를 계속 통과해야만 한다.) 
5. 테스트코드 또한 리펙토링한다. 
6. 구현해야 할 것이 있을 때까지 위의 작업을 반복한다. 

보통 TDD를 하다보면 자연스럽게 위처럼 행동하게 된다. 여기서 중요한 것은 테스트를 작성하고 테스트를 통과하는 코드를 만드는 과정은 빨라야 한다는 것이다. 이 주기가 빠르면 빠를수록 더욱더 많은 재미를 느낄 수 있을 것이다.

코드하나 고쳐보고 테스트 통과하고 조금 더 고쳐보고 통과하고 조금씩 성숙되어가는 코드를 보며 흐뭇함을 느끼기 바란다.

무엇이 좋은가?

그렇다면 이렇듯 테스트 코드를 먼저 작성하는 것에는 어떤 이득이 있을지 생각해 보자.

1. 테스트 코드에는 실제코드를 어떻게 써먹는지에 대한 설명이 자세하게 들어 있다.(인터페이스가 정의된다.) 
2. 따로이 테스트를 할 필요가 없다. 
3. 코드 수정시 기존의 테스트 코드를 통과하는지 체크되기 때문에 통합적인 테스트가 유지된다. 
4. 불안한 마음이 사라진다. 적어도 내가 생각할 수 있는 테스트는 모두 통과하였으므로.
5. 테스트 코드를 만드는 일은 쉬운일이 아니다. 내공이 쌓이면 쌓일수록 테스트 코드를 작성하는것이 어려워진다. 
   (깊이 있는 테스트코드가 만들어지기 때문이다.) 따라서 프로그래밍 실력이 향상된다.

무엇이 나쁜가?

TDD를 진행하는데 다소 거부감이 들 만한 사항이라면

1. 테스트코드가 추가되기 때문에 관리해야 하는 코드의 양이 많아진다.
2. 불안한 테스트코드는 오히려 역효과를 끼칠수도 있다.
3. 테스트코드를 만들기 위해서 불필요한 코드가 실제코드에 삽입될 수 있다.

불안한 테스트는 엉뚱한 결과를 간혹 초래한다. 테스트를 통과하기 때문에 안전하다고 여겼으나 테스트 자체의 오류인 경우 리팩토링시 코드가 엉망이 될 수도 있다.

또한 테스트를 위한 불필요한 코드가 많이 추가된다면 우선 자신이 설계한 프로그램의 구조를 다시 한번 살펴보는것이 좋다. 디자인을 개선할 수록 불필요한 코드는 사라질 것이다.

테스트 코드는 훌륭한 문서이다

테스트 코드를 기반으로 작성된 프로그램을 다른 사람이 관리해야 할 일이 생긴다면 어떻게 될까?

해당 프로그램을 넘겨받는 사람은 일단 프로그램이 어떤 의도로 만들어졌고, 어떻게 구현되었는지 알아야 할 것이다.

최선의 방법은 프로그램을 만든 사람이 며칠이고 함께 붙어 앉아서 완벽하게 이해시키는 것이 좋을 것이다. 하지만 대부분의 경우 그당시 모든것을 이해하더라도 혼자 남게 되면 막막해지고 처음부터 다시 뜯어 보지 않던가?

그렇다면 테스트 코드는 어떠한가? 테스트 코드에는 실제 코드가 발전한 역사(프로그램을 만든이의 의도를 파악할 수 있다.)가 고스란히 남아있고, 어떤 테스트를 행했는지 실제 코드가 어떻게 동작하는지 너무나 자세하게 나와 있다. 또한 무엇보다도 당장 테스트 코드를 실행해 볼 수 있다.

이보다 더 훌륭한 문서가 있을까?


TAG ,

댓글을 달아 주세요

1  ... 265 266 267 268 269 

글 보관함

카운터

Total : 196,909 / Today : 51 / Yesterday : 63
get rsstistory!