13 테스트 피라미드

개발 99·2025년 4월 29일

테스트 피라미드
1. E2E(end-to-end test)
API 테스트

  1. 통합 테스트
    여러 컴포넌트나 객체가 현력하는 상황을 검증하는 테스트
    애플리케이션 서비스 관점에서는 비즈니스 프로세스의 흐름을 검사하는 테스트
    서로 다른 모듈이나 시스템 간의 인터페이스를 테스트하는 것.
    장애 또는 예외 테스트

  2. 단위 테스트
    소프트웨어를 구성하는 가장 작은 단위를 검증하는 테스트(단위 = 함수, 메소드, 클래스,...)
    그래서 단위 테스트는 객체나 컴포넌트에 할당된 작은 책임 하나가 예상대로 작동하는지에 대한 테스트

1.에 가까워질수록 사용자의 실제 환경에 가까운 테스트이다.
(E2E는 API테스트나 UI테스트라고도 한다.)

이상적으로 단위 테스트 80%, 통합 테스트 15%, E2E 테스트 5%가 적절함.

단위 테스트 -> 통합 테스트 -> E2E 테스트 순으로 테스트를 작성해야 한다.

단위 테스트가 가장 중요하다.( E2E나 통합으로 세부적인 것까지 파악이 불가능하다. )

  • 비결정적 테스트
    어떤 때는 성공하고 어떤 때는 실패하는 테스트

구글의 테스트 피라미드

단위테스트, 통합테스트, E2E는 경계가 모호하다. 그래서 이것을 참고하자.

13.1 구글의 테스트 피라미드

  1. 대형 테스트
    멀티 서버에서 동작하는 테스트를 의미한다.

  2. 중형 테스트
    단일 서버에서 동작하되 멀티 프로세스, 멀티 스레드를 사용할 수 있는 테스트를 의미한다.

  3. 소형 테스트
    단일 서버, 단일 프로세스, 단일 스레드에서 동작하며, 디스크 I/O, 블로킹 호출이 없는 테스트를 의미한다.

13.2 테스트 분류 기준

새로운 테스트 분류 체계에 사용할 테스트 분류 기준은 무엇이 되면 좋을까?

  1. 테스트가 결정적인가?

  2. 테스트의 속도가 빠른가?

위 두 조건을 만족하는 테스트가 일반적으로 좋은 테스트라고 불린다.
즉, 테스트는 결정적이고 빠를수록 좋다.

13.2.1 테스트가 결정적이다

일관적이다와 동일한 의미.
즉 같은 코드를 대상으로 실행하는 테스트는 항상 같은 응답을 해야한다.
(비결정적인 테스트는 코드베이스에 아무런 조작을 하지 않았음에도 어떤 때는 성공하고 어떤 때는 실패한다.)

EX. H2를 이용해 스프링 테스트를 작성하는 예

public class PostServiceTest{
	
    @Autowired
    private PostService postService;
    
    @Test
    void postCreateDto(){
    	
        // given
    	PostCreate postCreate = PostCreate.builder()
        .writerId(1)
        .content("foobar")
        .build()
        ;
        
        // when
        Post result = postService.create(postCreate);
        
        // then
        assertThat(...)
        assertThat(...)
        assertThat(...)
    }
}

거라나 H2를 연동한 테스트는 비결정적으로 동작할 수 있다.

  • H2 프로세스의 상태에도 영향을 받고, 프로세스 간 통신 상태에도 영향을 받기 때문이다.

  • 병렬로 실행될 때 문제가 생길 수 있다.

13.2.2 테스트가 빠르다.

H2를 이용할 경우 그렇지 않은 테스트보다 속도가 더 느리다.

테스트 속도가 느린 이유는 스프링 컨테이너가 컨테이너를 초기화하는 시간, H2 데이터베이스 구동 및 종료에 걸리는 시간 때문이다.

테스트는 자주 실행을 해야하므로, 테스트 시간을 줄이는 것에 초점을 맞춰야 한다.

비결정적인 테스트가 만들어지는 이유

  1. 테스트가 병렬 처리를 사용할 경우

  2. 테스트가 디스크 I/O를 사용할 경우

  3. 테스트가 다른 프로세스와 통신할 경우

  4. 테스트가 외부 서버와 통신할 경우

속도가 느린 테스트가 만들어지는 이유

  1. 테스트가 블로킹 호출을 할 경우

  2. 테스트가 디스크 I/O를 사용할 경우

  3. 테스트가 다른 프로세스와 통신할 경우

  4. 테스트가 외부 서버와 통신할 경우

따라서, 블로킹 호출, 디스크 I/O, 다른 프로세스나 서버와 통신을 할 경우, 느려지고 비결정적으로 동작한다.

(테스트가 점유하는 리소스에 의존)

  • 소형 테스트
    시스템에 존재하는 대부분의 테스트는 소형 테스트로 작성되는 것이 좋다.

  • 중형 테스트
    H2를 이용한 테스트는 중형 테스트이다.(멀티 스레드, 멀티 프로세스)
    중형 테스트는 네트워크 호출이 여전히 불가하다.

  • 대형 테스트
    로컬 호스트가 아닌 다른 서버와 네트워크 호출이 가능해진다.
    (머신에 API 서버를 실제로 구동하고 Postman으로 확인을 해본다.)

13.3 소형 테스트의 중요성

핵심

  1. 시스템에는 소형 테스트가 많아야 한다.

  2. 중형 테스트나 대형 테스트가 소형 테스트보다 많아지는 것은 바람직하지 못하다.

  3. 소형 테스트는 단일 스레드, 단일 프로세스, 단일 서버에서 실행되면, 디스크 I/O, 블로킹 호출이 없는 테스트를 의미한다.

  4. H2를 이용한 테스트는 중형 테스트이다.

소형 테스트가 핵심이다. 트랙잿녀 스크립트 같은 코드 발생확률이 줄어든다.

애플리케이션 서비스는 리포지터리와 통신하는 경우가 많으므로, 중형 테스트이다.

트랜잭션 스크립트를 소형 테스트로 옮기기 위해서는 비지니스 로직을 도메인으로 옮긴다.

소형,중형,대형 테스트는 어느 부분을 테스트하느냐가 아니라 어떻게 테스트하냐에 따라 결정된다.

profile
구구구구구!

0개의 댓글