만드는 비용이 적고, 유지보수하기 쉽고, 빨리 실행되고, 안정적인 작은 크기의 테스트들에 대해 높은 커버리지를 유지해야한다.
테스트가 비싸질수록 테스트의 커버리지 목표는 낮게 잡아야한다. 그렇지 않으면 새로운 기능을 만드는 것보다 테스트를 만드는데 시간을 더 쓰게 된다.
위의 ‘시스템 테스트’, ‘통합 테스트’, ‘단위 테스트’의 정의는 맥락에 따라 다를 수 있다.
단위 테스트 → 일반적으로 하나의 클래스를 인스턴스화하고 해당 클래스의 인터페이스를 통해 기능들을 테스트
통합 테스트 → 연결된 여러 유닛을 인스턴스화하고 시작점이 되는 클래스의 인터페이스로 데이터를 보낸 후, 유닛들의 네트워크가 기대한대로 잘 동작하는지 검증
시스템 테스트 → 애플리케이션을 구성하는 모든 객체 네트워크를 가동시켜 특정 유스케이스가 전 계층에서 잘 동작하는지 검증
책 내의 Account에 대한 단위 테스트
만들고 이해하기 쉬운 편이고, 아주 빠르게 실행된다.
이런 식의 단위 테스트는 도메인 엔티티에 녹아 있는 비즈니스 규칙을 검증하기에 가장 적절한 방법이다.
테스트 가독성을 높이기 위해 행동-주도 개발에서 일반적으로 사용되는 방식으로 작성
이때 테스트에서 특정 메서드와 상호작용했는지 여부를 검증하는 경우
책 내의 예시 테스트는 단위 테스트지만 의존성의 상호작용을 테스트하고 있기 때문에 통합 테스트와 유사
웹 어댑터 테스트는 아래의 것들이 모두 기대한 대로 동작하는지 검증
웹 어댑터 테스트
MockMvc를 사용해 모킹했기 때문에 실제로 HTTP 프로토콜을 통해 테스트한 것은 아니다.
- 위에 나온대로 프레임워크를 테스트할 필요는 없다.
- Why?
- 프레임워크는 이미 똑똑하신 분들이 많은 검증을 거쳐서 만들어 놓으신 것이다. 바퀴를 다시 만들 필요는 없다는 말과 같은 의미이다.
- 이러한 맥락을 바탕으로 테스트가 필요한 것, 필요 없는 것을 구분하는 것도 매우 중요한 포인트라고 생각한다.
웹 어댑터 테스트와 비슷한 이유로, 영속성 어댑터도 통합 테스트 적용이 합리적이다.
@DataJpaTest 사용
이 테스트에서 DB를 모킹하지 않는다.
모킹을 이용할 경우, 실제 DB와 연동했을 때, SQL 구문의 오류나 DB 테이블과 자바 객체 간의 매핑 에러 등으로 문제가 생길 확률이 높아지기 때문!
스프링에서는 기본적으로 인메모리 DB를 테스트에서 사용한다. 하지만 프로덕션 환경에서 인메모리 DB를 사용하는 경우는 적기 때문에, 인메모리 DB에서 테스트를 통과했더라도 실제 DB에서 문제가 생길수도 있다. (DB 방언 같은 것 때문에..!)
시스템 테스트는 전체 애플리케이션을 띄우고 API를 통해 요청을 보내고, 모든 계층이 조화롭게 잘 동작하는지 검증한다.
@SpringBootTest 사용
MockMvc가 아닌 TestRestTemplate를 이용
실제 HTTP 통신을 하는 것처럼 실제 출력 어댑터도 사용
지저분한 로직들은 헬퍼 메서드 안으로 숨겼다. → 가독성 증가
시스템 테스트는 훨씬 더 실제 사용자와 유사하다. → 사용자 관점에서 애플리케이션을 검증할 수 있다.
시스템 테스트는 단위 테스트와 통합 테스트가 발견하는 버그와는 또 다른 종류의 버그를 발견해서 수정할 수 있게 해준다.
시스템 테스트는 여러 개의 유스케이스를 결합해서 시나리오를 만들 때 더 빛이 난다.
- 잘못된 지표보다는 절대적이지 않은 지표라고 보는게 맞다고 생각한다.
- 라인 커버리지가 높다고 검증이 잘 된, 잘 만들어진 프로젝트라고 할 수는 없다.
- 하지만 라인커버리지가 낮으면 보통 검증이 제대로 되지 않은, 테스트가 여러 상황을 커버하지 못하는 프로젝트이다.
- 물론 상황마다 다르겠지만, 외부와 분리된 도메인 코드들이 들어있는 패키지의 커버리지가 매우 낮게 나온다면 그것은 주의깊게 다시 확인할 필요가 있다고 생각한다.
얼마나 마음 편하게 SW를 배포할 수 있느냐를 테스트의 성공 기준으로 잡는 것이 좋다!
각각의 프로덕션 버그에 대해서 테스트가 그 버그를 잡지 못한 이유에 대해 생각하고, 기록하고 커버할 수 있는 테스트를 추가하는 것이 중요!
책에서 소개하는 육각형 아키텍처에서 사용하는 테스트 전략
테스트 작성 시 주의 사항
육각형 아키텍처는 도메인 로직과 바깥으로 향한 어댑터를 깔끔하게 분리
입출력 포트는 테스트에서 아주 뚜렷한 모킹 지점
모킹하는 것이 너무 버겁거나, 코드의 특정 부분을 커버하기 위해 어떤 종류의 테스트를 써야할지 모르겠다.