ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 8. 통합 테스트를 하는 이유
    개발 도서/Unit Testing 2024. 6. 20. 22:23

    이 장에서는 아래와 같은 내용을 다룬다.

    • 통합 테스트의 역할 이해
    • 테스트 피라미드의 개념 자세히 살피기
    • 가치 있는 통합 테스트 작성

     

    8.1 통합 테스트는 무엇인가?

     

    8.1.1 통합 테스트의 역할

     

    통합 테스트는 단위 테스트가 아닌 테스트에 해당한다.
    통합 테스트는 시스템이 프로세스 외부 의존성과 통합해 작동하는 방식을 검증한다.

    • 통합 테스트는 컨트롤러를 다루고, 단위 테스트는 알고리즘과 도메인 모델을 다룬다.
    • 통합 테스트는 회귀 방지와 리팩터링 내성이 우수하고, 단위 테스트는 유지 보수성과 피드백 속도가 우수하다.

     

    8.1.2 다시 보는 테스트 피라미드

     

    통합 테스트의 기준은 단위 테스트보다 높다.
    통합 테스트에서 회귀 방지와 리팩토링 내성 지표에 대한 점수는 단위 테스트보다 유지 보수성과 피드백 속도가 떨어진 만큼은 높아야 한다.
    테스트 피라미드가 이러한 절충을 나타낸다.
    대부분의 테스트는 빠르면서 비용이 낮아야 하고, 시스템이 전체적으로 올바른지 확인하는 통합 테스트는 속도가 느리고 비용이 많이 발생하므로 그 수가 적어야 한다.

    • 단위 테스트를 통해 가능한 한 많은 비즈니스 시나리오의 예외 상황을 확인하라. 통합 테스트를 사용해서 하나의 주요 흐름과 단위 테스트로 확인할 수 없는 예외 상황을 다루도록 하라.
    • 테스트 피라미드의 모양은 프로젝트 복잡도에 따라 달라진다. 간단한 프로젝트는 도메인 모델에 코드가 거의 없으므로 단위 테스트와 통합 테스트의 개수가 동일하다. 아주 단순한 경우 단위 테스트가 없을 수도 있다.

     

    8.1.3 빠른 테스트와 빠른 실패

     

    빠른 실패 원칙은 버그가 빠르게 나타날 수 있도록 하며 통합 테스트에서 할 수 있는 대안이다.

     

    8.2 어떤 프로세스 외부 의존성을 직접 테스트해야 하는가?

     

    8.2.1 프로세스 외부 의존성의 두 가지 유형

     

    관리 의존성은 애플리케이션을 통해서만 접근할 수 있는 프로세스 외부 의존성이다.
    관리 의존성과의 상호 작용은 외부에서 관찰할 수 없다. 대표적인 예는 애플리케이션 데이터베이스다.

     

    비관리 의존성은 다른 애플리케이션이 접근할 수 있는 프로세스 외부 의존성이다.
    비관리 의존성과의 상호 작용은 외부에서 관찰할 수 있다. 대표적인 예로 SMTP 서버나 메시지 버스 등이 있다.

     

    관리 의존성과의 통신은 구현 세부 사항이고, 비관리 의존성과의 통신은 식별할 수 있는 동작이다.

     

    통합 테스트에서 관리 의존성은 실제 인스턴스를 사용하라.
    비관리 의존성은 목으로 대체하라.

     

    8.2.2 관리 의존성이면서 비관리 의존성인 프로세스 외부 의존성 다루기

     

    때로는 관리 의존성과 비관리 의존성 모두의 특성을 나타내는 프로세스 외부 의존성이 있다.
    전형적인 예로는 다른 애플리케이션이 접근할 수 있는 데이터베이스가 있다.

     

    비관리 의존성의 식별 가능한 부분을 비관리 의존성으로 간주하고, 테스트에서 해당 부분을 목으로 대체하라.
    나머지 부분을 관리 의존성으로 간주하고, 해당 부분과의 상호 작용 대신 최종 상태를 검증하라.

     

    8.3 통합 테스트 예제

     

    해당 절에서는 통합 테스트에 대한 예제를 소개한다.
    앞서 언급했듯이, 단위 테스트로는 수행할 수 없는 모든 예외 사항과 가장 긴 흐름을 주된 테스트 시나리오로 잡는다.

     

    통합 테스트는 관리 의존성과 작동하는 모든 계층을 거쳐야 한다.
    데이터베이스를 예로 들면, 입력 매개변수로 사용한 데이터와 별개로 해당 데이터베이스의 상태를 확인하는 것을 의미한다.

     

    아래는 책에 기재된 그림으로, 핵심적이라 생각되는 부분이라 첨부한다.
    엔드 투 엔드 테스트와 통합 테스트의 차이에 관한 내용이다.

     


    엔드 투 엔드 테스트는 외부 클라이언트를 모방하므로, 테스트 범위에 포함된 모든 프로세스 외부 의존성을 참조하는 배포된 버전의 애플리케이션을 테스트한다.
    엔드 투 엔드 테스트는 관리 의존성(데이터베이스 등)을 직접 확인해서는 안되고, 애플리케이션을 통해 간접적으로 확인해

    야 한다.

     


    통합 테스트는 동일한 프로세스 내에서 애플리케이션을 호스팅한다.
    엔드 투 엔드 테스트와 달리 비관리 의존성을 목으로 대체한다.
    통합 테스트를 위한 프로세스 외부 의존성은 관리 의존성 뿐이다.

     

    엔드 투 엔드 테스트는 통합 테스트의 하위 집합이다.
    다만 통합 테스트는 필수적인 위치에 있으나, 엔드 투 엔드 테스트는 선택적인 위치에 있다.
    배포 후 프로젝트의 상태 점검을 위해 가장 긴 주요 흐름을 한개 혹은 두개 정도 테스트 할 수 있다.

     

    8.4 의존성 추상화를 위한 인터페이스 사용

     

    8.4.1 인터페이스와 느슨한 결합

     

    구현이 하나뿐인 인터페이스는 추상화가 아니며 해당 인터페이스를 구현하는 구체 클래스보다 결합도가 낮지 않다.
    이러한 인터페이스에 대한 향후 구현을 예상하면 YAGNI 원칙을 위배한다.
    YAGNI 원칙 : 현재 필요하지 않은 기능에 시간을 들이지 말라는 원칙

     

    8.4.2 프로세스 외부 의존성에 인터페이스를 사용하는 이유는 무엇인가?

     

    구현이 하나 뿐인 인터페이스를 사용하기에 타당한 이유는 목을 사용하기 위한 것 뿐이다.
    비관리 의존성에만 사용하고, 관리 의존성에는 구체 클래스를 사용하라.

     

    8.4.3 프로세스 내부 의존성을 위한 인터페이스 사용

     

    프로세스 내부 의존성에 대해 구현이 하나뿐인 인터페이스는 좋지 않다.
    이러한 인터페이스는 목을 사용해 도메인 클래스 간의 상호 작용을 확인하게 되고, 테스트가 코드의 구현 세부 사항에 결합된다.

    위 내용이 완벽히 이해가 되지 않는데, 11장에서 해당 주제로 더 깊이 소개한다고 하니 일단은 넘어가자...

     

    8.5 통합 테스트 모범 사례

     

    8.5.1 도메인 모델 경계 명시하기

     

    도메인 모델을 코드베이스에 명시적이고 잘 알려진 위치에 둬라.
    도메인 클래스와 컨트롤러 사이의 경계가 명확하면 단위 테스트와 통합 테스트를 좀 더 쉽게 구분할 수 있다.

     

    8.5.2 계층 수 줄이기

     

    간접 계층이 너무 많으면 코드를 추론하기가 어려워진다. 간접 계층을 가능한 한 적게 하라.
    대부분 백엔드 시스템은 도메인 모델, 애플리케이션 서비스 계층(컨트롤러), 인프라 계층, 이 세 가지 계층이면 충분하다.

     

    8.5.3 순환 의존성 제거하기

     

    순환 의존성이 있으면 코드를 이해하려고 할 때 알아야 하는 부담이 커진다.
    대표적인 예는 콜백(수신자가 발신자에게 작업 결과를 알리는 경우)이다.
    값 객체를 도입해 순환을 없애고, 호출부에 주는 결과를 값 객체로 전환하라.

     

    8.5.4 테스트에서 다중 실행 구절 사용

     

    테스트에 여러 실행 구절이 있는 것은 올바른 상태가 되기 어려운 프로세스 외부 의존성으로 작동하는 경우에만 타당하다.
    단위 테스트는 프로세스 외부 의존성으로 수행되지 않기 때문에 여러 가지 실행을 해서는 안된다.
    다단계 테스트는 대부분 엔드 투 엔드 테스트 범주에 속한다.

     

    8.6 로깅 기능을 테스트하는 방법

     

    8.6.1 로깅을 테스트해야 하는가?

     

    로딩은 두가지 종류가 있다.

    지원 로깅

    • 지원 담당자나 시스템 관리자가 추적할 수 있는 메시지를 생성한다.
      진단 로깅
    • 개발자가 애플리케이션 내부 상황을 파악할 수 있도록 돕는다.

    지원 로깅은 애플리케이션의 식별할 수 있는 동작이다.
    진단 로깅은 구현 세부 사항이다.
    테스트에 관한 다른 기능의 기준과 동일하게, 지원 로깅은 테스트가 필요하며 진단 로깅은 테스트가 필요하지 않다.

     

    8.6.2 로깅을 어떻게 테스트해야 하는가?

     

    지원 로깅은 비즈니스 요구 사항이므로 해당 요구 사항을 코드베이스에 명시적으로 반영하라.
    비즈니스에 필요한 모든 지원 로깅이 나열돼 있는 특별한 DomainLogger 클래스를 도입하라.

     

    지원 로깅을 프로세스 외부 의존성으로 작동하는 다른 기능처럼 취급하라.
    도메인 이벤트를 사용해 도메인 모델의 변경 사항을 추적하라.
    컨트롤러에서 도메인 이벤트를 DomainLogger 호출로 변환하라.

     

    진단 로깅을 테스트하지 말라.
    지원 로깅과 달리 도메인 모델에서 직접 진단 로그를 남길 수도 있다.

     

    8.6.3 로깅이 얼마나 많으면 충분한가?

     

    진단 로깅은 가끔 사용하라.
    진단 로깅을 너무 많이 쓰면 코드를 복잡하게 하고 로그의 신호 대비 잡음 비율이 나빠진다.
    이상적으로는 진단 로깅을 처리되지 않는 예외에 대해서만 사용해야 한다.

     

    8.6.4 로거 인스턴스를 어떻게 전달하는가?

     

    항상 모든 의존성(로거 포함)을 생성자 또는 메서드 인수를 통해 명시적으로 주입하라.

Designed by Tistory.