테스트 범위
하나의 기능이 올바르게 동작하려면 컨트롤러, 서비스, 모델과 같은 자바 코드와 프레임워크, 설정에 문제가 없어야 할 뿐 아니라 브라우저에서 실행되는 자바스크립트 코드, HTML과 CSS 등이 정상 동작해야 한다. 또한, DB의 테이블도 올바르게 생성해야한다.
기능 테스트와 E2E테스트
기능 테스트(Functional Testing)는 사용자 입장에서 시스템이 제공하는 기능이 올바르게 동작하는지 확인한다. 이 테스트를 수행하려면 시스템을 구동하고 사용하는데 필요한 모든 구성요소가 필요하다.
기능 테스트는 사용자가 직접 사용하느 웹 브라우저나 모바일 앱부터 시작해서 데이터베이스나 외부 서비스에 이르기까지 모든 구성 요소를 하나로 엮어서 진행한다. 기능 테스트는 끝에서 끝가지 올바른지 검사하기 때문에 E2E(End to End)테스트로도 볼 수 있다.
통합테스트
통합 테스트(Integration Testing)는 시스템의 각 구성 요소가 올바르게 연동되는지 확인한다. 기능 테스트가 사용자 입장에서 테스트하는데 반해 통합 테스트는 소프트웨어의 코드를 직접 테스트한다.
단위 테스트
단위 테스트(Unit Testing)는 개별 코드나 컴포넌트가 기대한대로 동작하는지 확인한다. 지금까지 이 책에서 살펴본 테스트가 주로 단위 테스트 코드이다. 단위 테스트는 한 클래스나 한 메서드와 같은 작은 범위를 테스트한다.
테스트 범위 간 차이
- 통합 테스트를 실행하려면 DB나 캐시 서버와 같은 연동 대상을 구성해야 한다. 기능 테스트를 실행하려면 웹 서버를 구동하거나 모바일 앱을 폰에 설치해야 할 수도 있다. 또한, 통합 테스트나 기능 테스트는 테스트 상황을 만들어내기 위해 많은 노력이 필요하다. 반면에 단위 테스트는 테스트 코드를 빼면 따로 준비할 것이 없다.
- 통합 테스트는 DB 연결, 소켓 통신, 스프링 컨테이너 초기화와 같이 테스트 실행 속도를 느리게 만드는 요인이 많다. 기능 테스트는 추가로 브라우저나 앱을 구동하고 화면의 흐름에 따라 알맞은 상호 작용을 해야 한다. 반면에 단위 테스트는 서버를 구동하거나 DB를 준비할 필요가 없다. 테스트 대상이 의존하는 기능을 대역으로 처리하면 되므로 테스트 실행 속도가 빠르다.
- 통합 테스트나 기능 테스트로는 상황을 준비하거나 결과 확인이 어렵거나 불가능할 때가 있다. 외부 시스템과 연동해야 하는 기능이 특히 그렇다. 이런 경우에는 단위 테스트와 대역을 조합해서 상황을 만들고 결과를 확인해야 한다.
테스트 범위에 따른 테스트 코드 개수와 시간
테스트를 자동화한다는 것은 결국 코드로 작성한 테스트를 실행한다는 것을 의미한다. 통합 테스트는 기능 테스트에 비해 제약이 덜하다. 단위 테스트는 통합 테스트로도 만들기 힘든 상황을 쉽게 구성할 수 있다. 기능테스트나 통합 테스트에서 모든 예외 상황을 테스트하면 단위 테스트는 줄어든다.
외부 연동이 필요한 테스트 예
모든 외부 연동 대상을 통합 테스트에서 다룰수 없지만 일부 외부 대상은 어느정도 수준에서 제어가 가능하다.
WireMock을 이용한 REST 클라이언트 테스트
통합 테스트 하기 어려운 대상이 외부서버이다. WireMock을 사용하면 서버 API를 스텁으로 대체할 수 있다.
WireMockServer는 HTTP 서버를 흉내 낸다.
- 테스트 실행 전에 WireMockServer를 시작한다. 실제 HTTP 서버가 뜬다.
- 테스트에서 WireMockServer의 동작을 기술한다.
- HTTP 연동을 수행하는 테스트를 실행한다.
- 테스트 실행 후에 WireMockServer를 중지한다.
스프링 부트의 내장 서버를 이용한 API 기능 테스트
스프링 부트를 사용한다면 API에 대한 테스트를 JUnit 코드로 작성 할 수 있다.
Refence.