•
테스트를 분류하는 가장 일반적이고 대중적인 분류 체계로 이 체계에서는 테스트를 단위 테스트, 통합 테스트, E2E 테스트의 3단 피라미드 형태로 분류한다.
•
테스트 피라미드의 y축은 테스트가 실제 사용자의 사용 사례와 얼마나 가까운지를 나타내는데, 위쪽에 위치할수록 아래에 있는 테스트보다 실제 환경에 가까운 테스트라고 볼 수 있다.
•
테스트 피라미드의 각 계층에 대한 일반적인 설명은 다음과 같다.
1.
단위 테스트
•
단위 테스트는 소프트웨어를 구성하는 가장 작은 단위를 검증하는 테스트를 의미한다.
•
여기서 말하는 Unit이란 통상적으로 함수, 메소드, 클래스 같은 개별적이고 작은 코드 조각을 지칭한다.
•
따라서 단위 테스트란 객체나 컴포넌트에 할당된 작은 책임이 예상대로 동작하는지 확인하는 테스트라고 볼 수 있다.
2.
통합 테스트
•
통합 테스트는 여러 컴포넌트나 객체가 협력하는 상황을 검증하는 테스트를 말한다.
•
즉, 통합 테스트는 독립적으로 만들었던 객체들이 상호작용하면서 생길 수 있는 상황을 검증한다.
◦
객체지향 관점에서 본다면 객체들의 협력이 제대로 이뤄지는지 평가하는 단계다.
◦
어플리케이션 서비스 관점에서 본다면 비즈니스 프로세스의 흐름을 검사하는 단계다.
•
통합 테스트를 조금 더 추상화시키면 서로 다른 모듈이나 시스템 간의 인터페이스를 테스트하는 것이라 볼 수도 있다.
◦
이때문에 통합 테스트는 연동 시스템의 장애나 예외 상황이 발생했을 때, 시스템이 어떻게 대처하는지 테스트하는 역할을 하기도 한다.
3.
E2E 테스트
•
실제 사용자 시나리오에서 시스템이 어떻게 동작하는지를 검증하는 테스트를 말한다.
•
백엔드 개발자 입장에서 종종 API 테스트라고 부르기도 하는데, 백엔드 ㅅ버를 실행하고 해당 서버에 필요한 하위 컴포넌트를 모두 구동시킨 후 API를 호출하는 방식으로 테스트를 작성하기 때문이다.
•
이처럼 테스트를 어떤 식으로 분류하는 지도 설명하지만 각 분류가 시스템에 얼마나 분포해야 하는지도 직관적으로 설명한다.
◦
단위 테스트가 가장 많고, 그 다음이 통합, E2E 순으로 말이다. 이상적으로는 각각 80%, 15%, 5%가 좋다고 한다.
•
더불어 테스트를 작성해야할 때, 우선순위에 대한 힌트도 얻을 수 있다. 피라미드를 만들 때 가장 아래부터 만드는 것처럼 단위 테스트부터 차례대로 만들어야 함을 나타낸다.
•
이렇기 때문에 가장 많이 작성하고 가장 먼저 작성되는 단위 테스트가 제일 중요하다고 할 수 있다.
•
저자는 이런 전통적인 테스트 피라미드에 대한 불만을 가지고 있기 때문에 이보다 더 낫다고 생각하는 구글의 테스트 피라미드를 소개한다.
◦
그 정의가 모호하기 때문이다. 단위 테스트에서 의미하는 그 단위란 무엇인가?
◦
어디까지 통합되어야 통합 테스트의 범주에 들어가는 것일까?
1. 구글의 테스트 피라미드
•
구글의 테스트 피라미드는 소형 - 중형 - 대형으로 이뤄졌다.
•
인지 모델 자체는 명칭만 달라 보인다. 구글은 단위니 통합이니 그런 단어들을 사용하는 대신 대형, 중형 테스트라는 용어를 사용한다.
•
이는 테스트의 크기에 따라 테스트를 분류하는 것인데, 여기서 말하는 테스트의 크기란 테스트를 실행하기 위해 사용하는 자원의 크기를 말한다.
1.
소형 테스트 : 단일 서버, 단일 프로세스, 단일 스레드에서 동작하며 디스크 입출력, 블로킹 호출이 없는 테스트를 의미한다.
2.
중형 테스트 : 단일 서버에서 동작하되 멀티 프로세스, 멀티 스레드를 사용할 수 있는 테스트를 말한다.
3.
대형 테스트 : 멀티 서버에서 동작하는 테스트를 말한다.
•
표로 표현하면 다음과 같다.
멀티 스레드 | 멀티 프로세스 | 멀티 서버 | |
소형 테스트 | X | X | X |
중형 테스트 | O | O | X |
대형 테스트 | O | O | O |
•
구글은 왜 테스트를 실행하는 데 사용되는 자원의 크기를 기준으로 이런 분류 체계를 만들게 되었을까?
2. 테스트 분류 기준
•
새로운 테스트 분류 체계에 사용할 테스트 분류 기준은 무엇이 되면 좋을까?라는 질문에 구글은 다음과 같이 대답했다.
1.
테스트가 결정적인가?
2.
테스트의 속도가 빠른가?
•
구글이 생각하는 테스트를 구분 짓는 주요 특징은 위 두 가지다. 바로 테스트의 결정성과 속도다. 일반적으로 이 두 조건을 만족시키는 테스트가 좋은 테스트라고 불리기 때문이다.
◦
테스트가 결정적이라는 건 무슨 의미일까? 일관된이라는 표현으로 이해해도 괜찮다. 즉, 같은 코드를 대상으로 실행하는 테스트는 항상 같은 결과를 내야 한다는 의미다.
▪
매번 실행 시 결과가 달라지는 테스트를 비결정적인 테스트라고 하며 생각보다 우리 주변에서 자주 찾아볼 수 있다.
•
그렇다면 좋지 않은 테스트는 어떨 때 만들어지는 것일까?
•
먼저 테스트가 비결정적으로 동작하게 되는 경우는 다음과 같다.
◦
테스트가 병렬 처리를 사용할 경우
◦
테스트가 디스크 입출력을 할 경우
◦
테스트가 다른 프로세스와 통신할 경우
◦
테스트가 외부 서버와 통신할 경우
•
속도가 느려지는 경우는 다음과 같다.
◦
테스트가 블로킹 호출을 사용할 경우
◦
테스트가 디스크 입출력을 사용하는 경우
◦
테스트가 다른 프로세스와 통신할 경우
◦
테스트가 외부 서버와 통신할 경우
•
즉, 테스트는 블로킹 호출, 디스크 입출력 등이 있을 때 느려지고 비결정적으로 동작하는데, 즉 테스트가 점유하는 자원의 양이나 종류에 따라 테스트의 형태가 결정된다.
•
소형 테스트의 표면적인 목표는 테스트를 단일 서버, 단일 프로세스, 단일 스레드로 만드는 만드는 것이라 볼 수 있지만 실질적이 목표는 테스트를 결정적이고 빠르게 만드는 것이다.
•
중형 테스트는 좀 더 완화된 기준을 가지나 멀티 서버를 금지하기 때문에 여전히 네트워크 호출은 금지한다.
•
대형 테스트의 경우, 모든 테스트를 로컬에서만 처리할 수 없기 때문에 서버를 여러대 띄워야하는 경우 사용한다.
•
각 테스트의 분류를 리소스가 아닌 의미론적 기준으로 분류한다면 다음과 같이 분류할 수도 있다.
결정적인가? | 빠른가? | |
소형 | O | O |
중형 | X | △ |
대형 | X | X |
3. 소형 테스트의 중요성
•
이번 장을 마무리하면서 반드시 기억해야할 인사이트는 다음과 같다.
◦
시스템에는 소형 테스트가 많아야 한다.
◦
중형 테스트나 대형 테스트가 소형 테스트보다 많아지는 것은 바람직하지 않은 현상이다.
◦
소혀 테스트는 단일 스레드, 단일 프로세스, 단일 서버에서 실행되며 디스크 입출력, 블로킹 호출이 없는 테스트다.
◦
H2를 이용하는 테스트는 중형 테스트이다.
•
저자는 소형 테스트를 다시 한번 강조한다.
◦
소형 테스트를 작성하기 위해 책임을 분배하다보면 트랜잭션 스크립트같은 코드가 나올 확률이 줄어 든다.
•
마지막으로 소형, 중형, 대형 테스트는 어떤 컴포넌트를 테스트하느냐에 따라 분류되지 않음을 기억하자.