테스트 코드와 테스트 주도 개발(TDD)

작성일

이 포스팅은 데브레인(debrains) 프로젝트 진행 시 팀 블로그에 작성했던 글입니다. (팀 블로그는 💣..)

이번 포스팅은 테스트 코드와 테스트 주도 개발(TDD) 관련된 내용입니다.

처음 사용해보는 기술인 만큼 내용이 부족할 수 있습니다. 양해 부탁드립니다.

많은 개발자분들은 이미 테스트 코드를 작성하고 계실거라 생각합니다. 저의 경우, 회사에서 프로젝트를 진행하다보면 기한에 맞춰 개발하기에 바빠 테스트 코드 작성은 생각도 못하고 있었습니다. 또한, 회사일은 제가 하고 싶은 것만 할 수 없기에.. 이리저리 휘둘리다 보니 백엔드 개발자로 지낸지 3년이 넘었지만 테스트 코드를 작성해본적이 없었습니다. (길게 적었지만 다~~ 변명입니다 ㅎㅎ;)

따라서, 이번 데브레인 프로젝트를 진행하면서 ‘테스트코드를 작성해보자! TDD를 해보자!’ 고 저를 포함한 백엔드 개발자 3명이서 다짐을 하게 됩니다.

테스트 주도 개발에 들어가기 전

우선, 테스트 코드란 코드 작성 시 문제가 없는지 확인하기 위해 사용합니다. 테스트 코드를 작성하는 이유는 아래와 같습니다.

  1. 빠른 피드백
  2. 자동검증이 가능
  3. 개발자가 만든 기능을 안전하게 보호

테스트 코드 작성 시 기본 패턴은 아래와 같습니다.

@Test
void TIL_조회() {
    // given

    // when

    // then
}

참고로 테스트 코드는 빌드 시 포함되지 않기 때문에 메소드 이름 한글로 적기도 합니다. 직관적으로 보기 좋기 때문이죠.

given - when - then 패턴

테스트 코드를 작성하는 패턴 중 하나이며, 준비 - 실행 - 검증 을 의미합니다.

테스트를 위한 준비 과정(given) - 실제로 액션을 하는 테스트를 실행하는 과정(when) - 테스트를 검증(then) 이라 할 수 있겠습니다.

[데브레인 Today I Learn(이하 TIL) 인증 횟수 계산] 에 대한 테스트 코드

private Object[] parametersForTotalCrtCnt() {
	return new Object[]{
			new Object[]{CycleStatus.EVERYDAY, 0, LocalDate.of(2022, 1, 30), LocalDate.of(2022, 1, 30), 1},
      new Object[]{CycleStatus.WEEK, 3, LocalDate.of(2022, 1, 1), LocalDate.of(2022, 1, 21), 9},
      new Object[]{CycleStatus.WEEK, 7, LocalDate.of(2022, 1, 30), LocalDate.of(2022, 2, 23), 25},
      new Object[]{CycleStatus.EVERYDAY, 0, LocalDate.of(2022, 1, 1), LocalDate.of(2022, 2, 12), 43}
	};
}

@Test
@Parameters(method = "parametersForTotalCrtCnt")
public void TIL_총_인증_횟수(CycleStatus cycleStatus, int cycleCnt, LocalDate startDate, LocalDate endDate, int totalCnt) {
	// given
	Til til = Til.builder()
				  .cycleStatus(cycleStatus)
          .cycleCnt(cycleCnt)
          .startDate(startDate)
          .endDate(endDate)
          .build();

	// when, 총 인증 횟수 계산
	til.totalCrtCount();

	// then
	assertThat(til.getTotalCnt()).isEqualTo(totalCnt);
}

처음 테스트 코드를 접해보는 입장에선 ‘왜 테스트 코드를 작성해야할까?’ 하는 의문이 들었습니다. 테스트 코드를 작성하다보면 시간도 더 투자해야하고 굳이 필요하진 않을 것이다 라는 생각을 가지고 있었지요..

간단한 프로젝트의 경우 필요가 없을 수도 있고 출력문을 통해 진행 할 수도 있습니다. 하지만, 몇만 라인이 넘어가는 프로젝트의 경우 테스트 코드 없이 개발 시 문제가 많이 생깁니다. 보통 프로젝트의 경우 처음 설계한대로 개발 후 끝! 인 경우가 거의 없죠. 하다보면 기능을 추가하게 되고 기능을 추가하면 또 다른 기능을 추가하고.. 이렇게 진행하다보면 아무리 잘짜여진 코드라도 틈이 생기기 마련입니다. 이 조그마한 틈이 장애가 발생하게 되겠지요! 😫 이를 방지 하기 위해 테스트 코드를 작성합니다.

이상 테스트 코드에 대해 알아보았는데요, 그렇다면 테스트 주도 개발은 무엇일까요?

테스트 주도 개발(TDD)이란 기능 구현 후 테스트 케이스를 작성하는 것이 아닌 테스트 케이스를 먼저 작성하고 기능 구현을 하는 것을 테스트 주도 개발이라 합니다. 즉, 테스트 코드 작성이 선행 되어야 하는 것입니다!

TDD의 장점으로는

  1. 객체 지향적인 코드 생산

    TDD는 기능 별 모듈화가 이루어지므로 코드의 재사용을 보장합니다.

  2. 디버깅 시간 감소

    TDD의 경우 유닛 테스트를 진행함으로써 DB의 문제인지, 비즈니스 코드의 문제인지 쉽게 찾아낼 수 있습니다.

  3. 추가 구현 시 용이함

    어떤 기능을 추가할 때 해당 기능이 기존의 코드에 영향을 미칠 수 있다는 점을 고려할 수 밖에 없는데요. TDD의 경우 자동화된 유닛 테스트를 진행함으로써 테스트 기간을 단축 시킬 수 있습니다.

이렇게 많은 장점이 있지만 TDD를 하기 어려운 이유는 습관을 바꾸기 힘들기 때문이지 않을까 싶습니다. 저같은 경우에도 테스트 주도 개발을 처음하는 입장에선 습관이 안잡혀 있어 어렵게 느껴진다는 부분이 가장 큰 단점으로 다가왔습니다.

그럼에도 불구하고 ‘TDD를 왜 사용해야 하는가’ 에 대해 묻는다면 개발자가 의도한대로 코드가 동작하는지 확인할 수 있고 이 과정에서 다양한 예외처리를 고려하면서 잠재적인 오류들에 대비할 수 있다는 점입니다.

그리고 제 개인적인 생각으로 테스트 코드를 먼저 작성 후 개발에 들어가니 예외처리에 대한 대비가 되어있어 실 코드 작성 시간은 얼마 걸리지 않았습니다. (물론, 테스트 코드 작성 시간이 많이 걸렸지만.. ;;)

마무리

이상, 테스트 코드와 테스트 주도 개발(TDD)에 대한 글이였습니다. 테스트 코드 작성에 대한 개발 습관이 아직 잡혀있지 않아 프로젝트를 진행하면서 어려운 점이 많았습니다. 일단 시간이 많이 들고 슬라이스 테스트로 진행할지 통합 테스트로 진행할지에 대한 부분도 고민이 많았죠.. 역시 습관이 중요한듯 합니다. TDD는 오히려 개발을 많이 접하지 않았던 분들이 습관을 잡기 훨씬 쉽다고 합니다. 아직 테스트 코드를 작성하고 계시지 않으시다면 이번 기회에 시도해 보시는 것도 앞으로 좋은 개발자로 성장하는데 좋은 밑거름이 될 것이라 생각합니다.

감사합니다.