TDD(Test-Driven Development)

jaden_94·2020년 9월 30일
0
post-thumbnail

Kent Beck 이 고안한 TDD 는 Extreme programming(xp) 을 위한 하나의 매커니즘 이라고 할 수 있다.
XP 는 급변하는 요구사항에 대응할 수 있는 개발방법론 중 하나인데,
TDD, Small Release, Simple Design 등등의 개념을 이용하여 지속적이고 빠른 요구사항의 변화에도 개발을 용이하게 할 수 있는 방법을 기술해 놓았다.

그렇다면, 도대체 TDD란 무엇인가?

TDD를 한글로 번역하자면 테스트 주도 개발 정도로 이해하면 된다.
TDD 개념이 확산되기 이전에 코드를 구현할 때는, 요구사항에 따라 어떤 로직이 수행되어야 할 지 계획을 하고 코드로 구현한 후 테스트 과정을 통해 코드가 올바르게 작동됨을 확인 하는 방식이였다면, TDD는 반대로 요구사항을 파악하면 다양한 테스트 케이스를 생각하고, 테스트 케이스들을 올바르게 수행하는 테스트 코드를 작성한 뒤, 테스트 코드를 바탕으로 구현할 코드를 작성하고, 필요에 따라 리팩토링 하는 과정을 거치게 된다.

그래서 무슨 말인데?

끄적여 놓은 글만으로는, 이해하기가 쉽지 않다. 원래 그렇다.

축구에서 나오는 공격자 반칙 중 하나이다. 자신의 편이 공격 진영에서 공보다 앞에 있을 때, 그 선수가 골키퍼를 포함한 상대편 최후방 2번째 수비수보다 상대 골라인에 가까이 있는 경우이고, 그 선수가 자기 편의 패스를 받게 되면 받는 반칙

라고 끄적여 놓으면, 오프사이드가 뭔 줄 아는 사람이 봐도 이 설명이 오프사이드에 대한 설명인지 알아보기 힘든 것 처럼 말이다..

그러므로 예시로 보는 TDD

요구사항이 생겼다. parameter로 1과 2를 받으면 3을 return 해야한다.
그리고, 2와 4를 받으면 6을 return 해야한다.
(쉬운 이해를 위해, 실제 상황과는 달리 요구사항이 구체적이고 명확해 해당 요구사항이 테스트 케이스가 됐다.)
테스트 코드를 작성하러 가보자.

@Test
    public void logic(){
        assertEquals(3, calculator.logic(1,2));
        assertEquals(6, calculator.logic(2,4));
    }

(Junit을 활용하면 TDD를 활용한 개발을 용이하게 할 수 있다)
내가 작성한 테스트 코드 logic()은 1,2를 paramete로 받으면 3을 return 해주길 기대하고 있다. 또한 2,4를 받으면 6을 return 해주길 기대한다.

그렇다면 logic()을 구현하러 가보자

 public int logic(int lhs, int rhs) {
        if(lhs == 1 && rhs == 2)
            return 3;
        if(lhs == 2 && rhs == 4)
            return 6;
        return -1;
    }

1,2 를 받으면 3을 리턴하고 2,4를 받으면 6을 리턴하며, 다른 값들을 받으면 -1을 리턴하는 logic()이란 코드를 구현했고, 이 코드는 요구사항에 알맞게 작동한다. TDD를 접목시킨 개발이 끝났다.

그런데, 다른 요구사항이 생겼다 5,6을 받으면 11을 리턴해야 한다. 다시 테스트 코드를 작성해보자

@Test
    public void logic(){
        assertEquals(3, calculator.logic(1,2));
        assertEquals(6, calculator.logic(2,4));
        assertEquals(11, calculator.logic(5,6));
    }

그리고 테스트 코드를 바탕으로 다시 logic()을 구현하면,

  public int logic(int lhs, int rhs) {
        if(lhs == 1 && rhs == 2)
            return 3;
        if(lhs == 2 && rhs == 4)
            return 6;
        if(lhs == 5 && rhs == 6)
            return 11;
        return -1;
    }

완성됐다.
요구사항에 완벽하게 맞춰 작동함으로, 이 코드는 100점짜리 코드이지만 코드를 조금 더 아름답고 깔끔하게 구현할 수 있지않을까? 리팩토링을 시작해보자

public int logic(int lhs, int rhs) {
        return lhs+rhs;
    }

리팩토링이 완료됐다.

결국 TDD는 이러한 것.

TDD를 활용하면, 과도한 설계로 인한 비용을 절약할 수 있다.
빗대어 설명하자면, 내게 지금 필요한게 특정 상황에 대한 오프사이드 규정이라면, 해당 상황이 오프사이드인지 아닌지 구현하면 된다. 축구에 대한 방대한 지식을 바탕으로 설계를 마치고 오프사이드를 완벽하게 구현할 필요는 없다.(생각해봐라 엄청난 설계를 바탕으로 가장 완벽한 오프사이드 규정을 만들었는데, 축구의 규칙이 바뀌면, 다시 오프사이드 규정을 설정하기 위해 또 엄청난 비용이 요구될 것이다.) 우선 요구사항에 맞는 코드를 구현하고 구현한 코드를 바탕으로 일반적이고 다양한 상황에서 올바르게 작동할 수 있도록 리팩토링하는 과정을 거치면 된다.

주의! 고작 며칠 전 시작함

TDD라는 개념을 며칠 전 공부하기 시작했다.
프로젝트를 진행하면서 필요한 것들을 서칭할때 Junit이라는 단어를 어디선가 많이 봤지만, 그게 도대체 뭐하는건데? 라는 생각만 해보았지 직접 Junit을 쓸 생각은 없었다. 하지만 프로그래밍 공부를 하다보면 결국 자주보이는 용어는 부딪치게 되는 것 같다. 여튼 TDD는 며칠 전 알게된 개념이고 내가 끄적인 글에는 곡해가 있을 수도 있다. 부디, 고수분들은 나의 무지를 신랄하게 댓글로 까주시고 고쳐주시길!

참고한 곳 : https://www.youtube.com/watch?v=xs-yhBlkbbQ

0개의 댓글