단위 테스트 (Unit Test)

단위 테스트가 왜 필요한지, 어떤 상황에 사용에 필요한지, 단위 테스트의 장점 등을 살펴보자.
Minha Sohn's avatar
Mar 31, 2024
단위 테스트 (Unit Test)
나는 이제 막 4개월차에 접어든 신입이다.
솔직히 아직 제대로 된 단위 테스트를 작성해본 적이 없다. TDD, 단위테스트 등 테스트가 중요하다는 얘기를 많이 들었지만 실제로 사용해볼 기회?가 없었던 것 같다.
그러다 오늘 우연히 나가는 개발 모임에서 단위테스트에 대한 얘기를 듣게 되었다.
말씀하신분은 10년차 개발자로 이번 회사에서 처음으로 개발 총괄을 담당하게 되셨다고 한다. 그래서 자연스럽게 개발팀의 인사도 담당하게 되셨는데, 자기가 어떤 기준으로 사람을 고용하는가에 대해 말씀하신 것 중 하나가 단위테스트 였다.
그 분의 이야기를 듣고 ‘나는 왜 단위 테스트를 해야한다고 생각하고 있나’ 라고 생각을 했을 때 어디서 들은 얘기 뿐 사실은 왜 필요한지 잘 이해하지 못하고 있었다.
그래서 이번 기회에 단위 테스트에 대해 정리하고 학습하여, 실제 사이드 프로젝트에 적용해보려고 한다.
 

단위 테스트를 하는 이유

  • 원하는 부분만 테스트를 함으로서 빠르게 제대로 동작 하는지 검증할 수 있다.
  • 코드 리팩토링을 안정적으로 할 수 있다.
    • 개발 초기에는 그 속도가 굉장히 느리다고 느낄 수도 있지만, 6개월만 지나도 테스트를 적용한 코드의 개발속도가 훨씬 빠르다는 것을 느낄 수 있다. - 10년차 개발팀장
 

단위 테스트를 하는 상황

  1. 처음 기능을 개발했을 때
      • 의도한 기능과 필요 조건에 따라 알맞게 동작하는지 간단하게 작성한다.
      • 함수를 생성하면 두고두고 계속 그 함수를 수정하는 경우가 많다. 그러다 원래 있던 가정이 깨져서 버그가 나는 경우가 허다하다.
  1. 해당 함수가 다른 사람들의 코드에 많이 사용될 여지가 있는 경우
      • 내가 의도한 방향과 다르게 함수를 사용했을 때
      • 누군가 내 의도와 다르게 함수를 수정했을 때
  1. 실제 프로덕션 상황에서 사용자의 인풋값에 따라 의도한 바와 다르게 동작하는 경우 (버그 발생)
      • 실제 에러가 나는 값을 대입하여 테스트 코드를 작성
 

단위 테스트의 장점

특히 3번의 경우,
프로덕션 상황에서 버그 발생시 실제 코드를 고치고 이를 확인하는 과정이 꽤나 오래 걸린다. (로컬에서 코드 수정 및 확인 ⇒ 빌드 ⇒ 테스트 서버에서 확인 ⇒ 실제 운영 서버 업데이트 등)
이 때 테스트 코드를 작성함으로서,
  • 쉽고 빠르게 버그를 수정 및 확인이 가능하다.
  • 테스트 코드가 문서의 역할을 하게된다. 즉, 처음 이 함수를 만들 때의 원래 설계 의도를 남길 수 있다.
    • 물론 처음부터 전부 문서화하고 테스트 코드를 작성할 수 있다면 좋겠지만 시간적 여유가 생각보다 많지 않다.
    • 모든 변수 상황을 고려하고 코드를 작성할 수 있다면 좋겠지만, 실제 서비스를 운영해야 알게 되는 버그들이 있다.
  • 매 빌드시에 단위 테스트가 작동한다. 따라서 빠르게 코드에 버그가 있을 때 빠르게 대처할 수 있다.
💭
어짜피 코드 작성 후 항상 제대로 동작하는지, 버그가 없는지를 고민하고 코드를 수정한다. 이 시간을 테스트 코드를 작성하는데 사용함으로서 현재 내 코드가 제대로 동작하는가를 확인하는 동시에 재사용이 가능한 검증 코드를 만들어 낼 수 있다.
 

단위 테스트 하는 요령

생각보다 단위 테스트를 작성하다보면 코드의 가독성이 떨어질 수 있다.
이럴 때는 given-when-then패턴을 사용해보자. (해당 패턴은 선택일 뿐 필수는 아니다)

given

테스트에 사용하는 값을 정의한다.

when

테스트하고자 하는 기능을 실행한다.

then

기능을 실행한 후 결과를 검증한다.
 

given-when-then 패턴 적용 전과 후

// 적용 전 @Test @DisplayName('자동차는 명령 받은 만큼 이동거리가 증가한다') void car_moves_as_ordered() { int orderedCount = 10; Car car = new Car(); car.moveAsOrdered(orderedCount); int distanceResult = car.getPosition(); assertThat(distanceResult).isEqualTo(orderdCount); }
// 적용 후 @Test @DisplayName('자동차는 명령 받은 만큼 이동거리가 증가한다') void car_moves_as_ordered() { // given int orderedCount = 10; Car car = new Car(); // when car.moveAsOrdered(orderedCount); int distanceResult = car.getPosition(); // then assertThat(distanceResult).isEqualTo(orderdCount); }
 

References

Share article

haccoon