1 분 소요

TDD 란?

테스트 주도 개발(Test-driven development TDD)은 매우 짧은 개발 사이클을 반복하는 소프트웨어 개발 프로세스 중 하나이다.
개발자는 먼저 요구사항을 검증하는 자동화된 테스트 케이스를 작성한다. 그런 후에, 그 테스트 케이스를 통과하기 위한 최소한의 코드를 생성한다.
마지막으로 작성한 코드를 표준에 맞도록 리팩토링한다. 이 기법을 개발했거나 ‘재발견’ 한 것으로 인정되는 Kent Beck은 2003년에 TDD가 단순한 설계를 장려하고 자신감을 불어넣어준다고 말하였다.
출처 : 위키백과

3줄 요약을 하자면

  1. 기능을 구현 할 때 테스트를 먼저 만든다.
  2. 테스트를 통과하기 위한 코드를 만든다.
  3. 테스트를 돌리며 리펙토링 한다.

요구사항 : 이벤트가 유효기간이 지낫는지 안지낫는지 판단하는 메서드

기능을 구현 할 때 테스트를 먼저 만든다.

// 이벤트 객체는 이미 작성되어있다 가정하겠습니다.
@Test
void isEventValidTest(){
    //given
    Event event = new Event();
    event.setEndDate(LocalDate.of(2025,01,01)); // 25년 1월 1일에 종료되는 이벤트라 가정하겠습니다.
  
    //when
    boolean valid = event.isEventValid();
  
    //then
    assertThat(valid).isTrue();
}

이벤트객체에 종료시점이란 정보를 주고 이벤트의 메서드를 호출해서 boolean으로 값을 리턴하여 검사하는 테스트를 작성해보았습니다.
isEventValid메서드를 구현하지 않았기에 테스트를 실행시 당연히 실패가 될껍니다.
이벤트객체에서 유효기간내에 이벤트인지 확인하는 메서드인 isEventValid를 이제 구현하여봅니다.

테스트를 통과하기 위한 코드를 만든다.

public boolean isEventValid(){
    // 22년 01월 30일 작성
    return LocalDate.now().isBefore(this.endDate);
  }

isEventValid를 구현하고 테스트를 돌려보겠습니다.
이제 해당 테스트는 성공할껍니다.
테스트가 통과되었으면 다른 경우를 가정하여 한번더 테스트를 작성해 검증하겠습니다.

@Test
void isEventValidTest(){
    //given
    Event event = new Event();
    event.setEndDate(LocalDate.of(2019,01,01)); // 19년 1월 1일에 종료되는 이벤트라 가정하겠습니다.
  
    //when
    boolean valid = event.isEventValid();
  
    //then
    assertThat(valid).isFalse();
}

해당 메서드에 실패를 가정한 값을 주어 정상적으로 실패처리 되었는지를 테스트 하였습니다. 예제가 간단하여 리펙토링하는 과정대신 요구사항이 하나 추가되어 리펙토링겸 추가 요구사항을 적용하여 보겠습니다.

테스트를 돌리며 리펙토링 한다.

추가 요구사항 : 종료기한이 없는 무종료기한의 이벤트가 추가되었다.(endDate가 null일수있음) (억지 예제 죄송합니다…)

원래 종료기한은 필수값이었지만 요구사항의 변경으로 이제 null일 경우도 체크해야합니다. 추가적인 테스트코드를 하나 작성합니다.

void isEventValidTest(){
    //given
    Event event = new Event();
    //when
    boolean valid = event.isEventValid()
    //then
    assertThat(valid).isTrue();
}

당연히 지금 테스트를 한다면 endDate가 null이라 NPE가 발생할것입니다. 추가 구현을 하도록 하겠습니다.

public boolean isEventValid(){
    if(Objects.isNull(endDate)){
        return true;
    } 
    
    return LocalDate.now().isBefore(this.endDate);
  }

isEventValid를 리펙토링하고 앞서 작성하였던 테스트코드들을 전부 실행합니다. 테스트가 전부 통과되었습니다.

isEventValid에 불필요한 if문이 있는거같아 리펙토링하겠습니다.

public boolean isEventValid(){
    // endDate가 null이거나 현재 날짜가 종료시점보다 전이라면 true
  return Objects.isNull(endDate)||LocalDate.now().isBefore(this.endDate);
}

기존 테스트코드를 실행 후 이상이 없다면 완료입니다.

이렇게 TDD를 기반으로 개발을 하게되면 빠르게 테스트하여 피드백을 받을수있습니다.
또한 추가 요구사항 개발에 기존 테스트코드를 활용하면 안정성을 증가하며 개발이 가능해집니다.

추가로 필자가 느끼기엔 TDD를 하기위해선 최대한 작게 나뉘어져있는 설계구조가 적합합니다.
자연스럽게 클린코드적으로 로직을 구성하게됩니다. 아니면 테스트를 짜는데 지옥도가 펼쳐집니다… TDD는 현재를 약간 손해보더라도 미래를 위해 투자하는것입니다.
유지보수되어야하고 지속 가능해야하는 서비스라면 꼭 시행해볼만한 개발방법론이라 생각합니다.

댓글남기기