이번 프로젝트를 리팩토링하면서 꼭 해보자 했던 것이 바로 테스트 코드 작성이었다. 이전에 통합 테스트를 해본 적은 있지만, 단위 테스트는 제대로 경험해본 적이 없었다. 시간에 쫓기다 보니 단위 테스트를 작성할 기회가 없었고, 중요하다는 것을 알았지만 항상 뒤로 미루다 작성하지 않았었다.
이번에는 단위 테스트를 통해 프로젝트의 안정성과 품질을 한층 더 높여보려고 단위 테스트란 무엇인지, 코드는 어떻게 짜는지에 대해 알아보려고 한다.
단위 테스트 (Unit Test)란?
단위 테스트(Unit Test)는 소프트웨어 테스트의 한 유형으로, 소프트웨어의 개별 구성 요소 또는 모듈이 예상대로 작동하는지 검증하는 과정이다. 여기서 "단위"는 보통 메서드, 함수, 또는 클래스와 같은 소프트웨어의 가장 작은 테스트 가능한 부분을 의미한다.
단위 테스트의 특징
- 독립성: 각 테스트는 다른 테스트와 독립적으로 실행되며, 테스트 간에 상호 의존성 X
- 빠른 실행: 단위 테스트는 비교적 적은 코드량을 테스트하기 때문에 빠르게 실행
- 모의 객체 사용: 단위 테스트에서는 외부 의존성(예: 데이터베이스, 파일 시스템 등)을 모의 객체(Mock Object)로 대체하여 테스트
- 세밀한 검증: 단위 테스트는 개별 구성 요소의 동작을 세밀하게 검증 가능
단위 테스트의 장점
- 빠른 실행 속도: 단위 테스트는 일반적으로 빠르게 실행되어 개발자가 즉시 피드백을 받을 수 있음
- 독립성: 각 테스트는 독립적으로 실행되며, 다른 테스트에 영향을 받지 않음
- 코드 커버리지 향상: 단위 테스트는 개별 구성 요소를 세밀하게 테스트하여 코드 커버리지를 높일 수 있음
- 디버깅 용이성: 특정 기능이나 메서드의 문제를 쉽게 찾아내고 수정 가능
단위 테스트의 단점
- 제한된 범위: 단위 테스트는 개별 구성 요소만 테스트하므로, 시스템 전체의 동작을 보장하지 않음
- 모킹의 복잡성: 복잡한 모킹 설정이 필요할 수 있으며, 모킹이 잘못되면 테스트의 신뢰성이 떨어질 수 있음
통합 테스트(Integration Test)란?
통합 테스트(Integration Test)는 소프트웨어의 개별 구성 요소들이 모여 전체 시스템에서 올바르게 동작하는지 검증하는 테스트 방법이다. 단위 테스트가 개별 모듈 또는 클래스의 기능을 검증하는 것에 초점을 맞춘다면, 통합 테스트는 이들 모듈이 서로 통합되어 상호작용할 때 발생할 수 있는 문제를 찾아내고 해결하는 데 중점을 둔다.
통합 테스트의 특징
- 모듈 간 상호작용 검증: 개별 모듈이 통합되어 동작할 때 발생할 수 있는 문제를 검증
- 실제 환경 테스트: 실제 운영 환경과 유사한 조건에서 테스트하여 시스템의 신뢰성을 높임
- 데이터 흐름 검증: 모듈 간의 데이터 흐름과 의존성을 테스트하여 데이터의 일관성과 정확성을 확인
- 종단 간 시나리오 테스트: 사용자 시나리오를 기반으로 시스템의 종단 간 기능을 테스트
통합 테스트의 장점
- 실제 환경에서의 신뢰성: 실제 운영 환경과 유사한 조건에서 테스트하여 시스템의 신뢰성을 높임
- 종단 간 검증: 시스템의 여러 부분이 함께 올바르게 작동하는지 검증하여 전체적인 기능을 확인
- 복잡한 문제 발견: 단위 테스트로는 발견하기 어려운 모듈 간 상호작용 문제를 찾아낼 수 있음
- 품질 보장: 시스템의 전체적인 품질을 높이고, 릴리즈 전에 잠재적인 문제를 사전에 발견하여 수정 가능
통합 테스트의 단점
- 느린 실행 속도: 여러 모듈을 포함하여 테스트하므로 단위 테스트보다 실행 속도가 느림
- 복잡한 설정: 실제 환경과 유사한 조건을 설정하는 것이 복잡하고 시간이 많이 소요될 수 있음
- 디버깅 어려움: 문제가 발생했을 때, 단위 테스트보다 원인을 찾기가 어려움
Test 방식
요즘 Java 단위 테스트 작성에는 크게 2가지 라이브러리가 사용된다.
JUnit, AssertJ 이란?
- JUnit5 : 자바 유닛(단위)테스트를 위한 테스팅 프레임워크
- AssertJ : 자바 테스트를 돕기 위해 다양한 문법을 지원하는 라이브러리
JUnit 만으로도 단위 테스트를 충분히 작성할 수 있다. 하지만 JUnit에서 제공하는 assertEquals()와 같은 메소드는 AssertJ가 주는 메소드에 비해 가독성이 떨어진다. 그렇기 때문에 순수 Java 애플리케이션에서 단위 테스트를 위해 JUnit5와 AssertJ 조합이 많이 사용된다.
given/ when/ then 패턴
given-when-then 패턴이란 1개의 단위 테스트를 3가지 단계로 나누어 처리하는 패턴으로, 각각의 단계는 다음을 의미한다.
- given(준비): 어떠한 데이터가 준비되었을 때
- when(실행): 어떠한 함수를 실행하면
- then(검증): 어떠한 결과가 나와야 한다.