넓은 범위 테스트
고친 사람 github-actions[bot]
넓은 범위 테스트는 시스템의 여러 부분이 함께 맞물려 제대로 도는지 한 번에 확인합니다. 함수 하나나 부분 둘이 아니라 여러 부분을 이은 흐름 전체를 봅니다. 부분마다 검사를 통과해도 합쳤을 때만 드러나는 고장이 있어서 둡니다. 종단 간 테스트와 시스템 테스트가 이 묶음에 듭니다.
쉽고 빠른 이해
무슨 일을 하나 — 여러 부분을 진짜로 이어 놓고 한 흐름을 끝까지 돌려 봅니다. 주문 요청 하나를 넣고 재고가 줄고 결제가 되고 주문이 저장되는지까지 보는 식입니다.
왜 하나 — 부분만 떼어 검사하면 부분끼리 주고받는 약속이 어긋난 것을 못 봅니다. 여러 부분이 합쳐져야 비로소 생기는 동작도 있습니다.
어떻게 도나
- 검사할 부분들을 전부 띄우고 서로 잇습니다
- 바깥 입구로 요청을 넣어 한 흐름을 끝까지 지나갑니다
- 흐름 끝에 남은 결과가 기대와 같은지 확인합니다
대가 — 느립니다. 코드가 멀쩡해도 가끔 깨집니다. 깨지면 여러 부분 중 어디가 문제인지부터 찾아야 합니다. 그래서 개수를 적게 둡니다.
언제 쓰나 — 가입 · 로그인 · 결제처럼 멈추면 사업이 멈추는 흐름에 몇 개만 둡니다. 갈래가 많은 계산은 함수 하나씩 떼어 보는 테스트에 맡깁니다.
상세
이 절은 쇼핑몰의 주문 기능 하나를 두고 넓은 범위 테스트를 봅니다. 주문 요청은 주문 서비스가 받습니다. 주문 서비스는 재고 서비스에 재고를 줄여 달라고 합니다. 결제 서비스에는 돈을 받아 달라고 합니다. 마지막으로 주문을 데이터베이스에 남깁니다.
자동차 공장은 엔진과 브레이크와 핸들을 하나씩 따로 검사합니다. 그래도 다 조립한 차는 도로에 끌고 나가 한 번 몰아 봅니다. 브레이크를 밟았을 때 차가 한쪽으로 쏠리는지는 부품 검사표 어디에도 안 나오기 때문입니다.
테스트의 범위는 테스트 하나가 확인하는 코드의 양입니다. 넓은 범위 테스트는 시스템의 서로 다른 여러 부분이 어떻게 맞물리는지를 확인합니다. 주문 서비스와 재고 서비스와 결제 서비스를 모두 이어 둡니다. 그 위에서 주문 한 건이 끝까지 가는지 보는 테스트가 그 예입니다.
영어로는 large-scoped test 또는 broad-scoped test 라고 부릅니다. 한 번에 확인하는 범위가 넓다는 뜻입니다.
범위로 나누는 세 계층
테스트를 범위로 나누면 대개 세 계층이 나옵니다. 아래 표는 주문 기능을 예로 들어 계층마다 무엇을 확인하는지 보입니다.
| 범위 | 확인하는 것 | 주문 기능에서의 예 | 흔히 부르는 이름 |
|---|---|---|---|
| 좁은 범위 | 클래스나 메서드 하나의 논리 | 할인 금액 계산 메서드가 맞는 값을 내나 | 단위 테스트 |
| 중간 범위 | 부분 몇 개 사이의 주고받기 | 주문 서비스가 데이터베이스에 주문을 저장하고 다시 읽나 | 통합 테스트 |
| 넓은 범위 | 여러 부분이 이어진 흐름 전체 | 주문 한 건이 재고 · 결제 · 저장까지 끝나나 | 종단 간 테스트 · 시스템 테스트 · 기능 테스트 |
표에서 볼 것은 아래 줄로 갈수록 「확인하는 것」이 한 부분에서 흐름 전체로 넓어진다는 점입니다. 좁은 범위 테스트는 한 부분의 계산이 맞는지만 봅니다. 중간 범위 테스트는 부분 둘이 만나는 경계를 봅니다. 넓은 범위 테스트는 그런 경계 여러 개를 한 번에 지나갑니다.
마지막 줄의 세 이름은 무엇을 따라 검사하느냐로 갈립니다. 아래 표가 그 기준입니다.
| 이름 | 무엇을 따라 검사하나 |
|---|---|
| 종단 간 테스트 | 사용자가 쓰는 흐름을 입구부터 끝까지 따라갑니다 |
| 시스템 테스트 | 다 합친 시스템 전체가 요구 사항대로 도는지 봅니다 |
| 기능 테스트 | 기능 하나하나가 요구대로 되는지 안쪽 코드를 보지 않고 확인합니다 |
따라가는 것은 달라도 확인하는 범위가 시스템 전체라는 점은 셋이 같습니다. 그래서 범위로 가르는 분류에서는 이들을 한 묶음으로 봅니다.
부분 사이에서 어긋나는 약속
넓은 범위 테스트가 잡으려는 고장은 크게 둘입니다. 첫째는 부분끼리 주고받는 약속이 어긋나는 고장입니다. 이 소절은 그 첫째를 봅니다.
좁은 범위 테스트는 검사하는 부분이 부르는 다른 부분을 가짜로 바꿔 끼웁니다. 진짜를 부르면 느리고 결과가 흔들리기 때문입니다. 이렇게 진짜 대신 끼우는 가짜가 테스트 더블입니다.
가짜는 테스트를 쓴 사람이 짐작한 대로만 답합니다. 주문 서비스 개발자는 결제 서비스가 회원 번호를 userId 라는 이름으로 받는다고 짐작하고 가짜를 만듭니다. 결제 서비스는 같은 값을 memberId 라는 이름으로 기다립니다. 두 서비스의 테스트는 각자 전부 통과합니다.
이 어긋남은 두 서비스를 진짜로 이어 요청을 한 번 흘려 봐야 드러납니다. 넓은 범위 테스트는 가짜 대신 진짜 부분들을 잇습니다. 그래서 짐작과 실물 사이의 틈이 테스트에서 먼저 보입니다.
한 부분에 적혀 있지 않은 동작
둘째 고장은 여러 부분이 합쳐져야 비로소 생기는 동작에서 납니다. 주문 한 건이 재고를 줄이고, 결제를 받고, 주문을 저장하는 순서는 어느 한 클래스에도 통째로 적혀 있지 않습니다. 세 부분이 차례로 일해야 그 흐름이 생깁니다.
결제가 실패하는 경우를 보면 더 뚜렷합니다. 이때 주문 서비스는 먼저 줄였던 재고를 되돌려야 합니다. 되돌림이 제대로 되는지는 주문 · 재고 · 결제 세 부분이 함께 돌아야 확인됩니다.
아래 그림은 이런 테스트 하나가 지나가는 길입니다.
flowchart TD
T["테스트 코드"] -->|"주문 요청 · 결과 조회"| O["주문 서비스"]
O -->|"① 재고 줄이기"| S["재고 서비스"]
O -->|"② 결제 요청"| P["결제 서비스"]
O -->|"③ 주문 저장"| D["데이터베이스"]
O -.->|"② 가 실패하면 재고 되돌리기"| S
테스트 코드는 주문 서비스의 입구로만 들어갑니다. 요청을 넣는 것도, 결과를 확인하는 것도 그 입구로 합니다.
주문 서비스에서 뻗은 번호 화살표는 테스트가 만든 것이 아닙니다. 주문 한 건이 원래 지나가는 순서입니다. 결제가 실패하면 점선을 따라 재고를 되돌립니다.
좁은 범위 테스트라면 이 화살표들 끝을 전부 가짜로 막았을 겁니다. 그러면 되돌림이 제대로 되는지는 확인할 수 없습니다.
실행하는 코드와 확인하는 코드
범위를 잴 때 헷갈리기 쉬운 점이 하나 있습니다. 테스트가 실행한 코드의 양과 확인한 코드의 양은 다릅니다. 범위는 확인한 쪽으로 잽니다.
할인 금액 계산 메서드를 검사하는 테스트를 떠올려 봅시다. 이 메서드는 안에서 세율 표 클래스를 부릅니다. 테스트가 세율 표를 가짜로 바꾸지 않았다면 세율 표 코드도 함께 실행됩니다.
그래도 이 테스트가 확인하는 것은 할인 금액 하나뿐입니다. 그러니 좁은 범위 테스트입니다. 넓은 범위 테스트는 여러 부분을 실행하는 데서 그치지 않습니다. 그 부분들이 이어져 만든 결과를 확인합니다.
크기와 범위는 다른 기준
테스트를 가르는 기준에는 범위 말고 크기도 있습니다. 테스트 크기는 테스트가 어디서 도는지로 잽니다. 아래 표처럼 도는 곳이 넓을수록 큰 테스트입니다.
| 크기 | 도는 곳 |
|---|---|
| 작은 테스트 | 프로세스 하나 |
| 중간 테스트 | 머신 한 대 |
| 큰 테스트 | 여러 머신 |
두 기준은 대개 함께 움직입니다. 좁은 범위 테스트는 작은 테스트로 도는 일이 많습니다. 넓은 범위 테스트는 중간이나 큰 테스트로 도는 일이 많습니다. 늘 그렇지는 않습니다.
주문 · 재고 · 결제 세 부분을 한 프로세스 안에 진짜로 엮은 테스트를 떠올려 봅시다. 데이터베이스만 메모리에서 도는 대용품으로 바꿉니다. 이 테스트는 확인하는 범위가 넓습니다. 그런데 도는 곳이 프로세스 하나라서 크기로는 작은 테스트입니다.
범위와 크기를 두 축으로 따로 세는 분류는 구글이 자기 테스트 관행을 정리하며 쓴 틀입니다. 이 틀에서 작은 · 중간 · 큰 테스트는 크기를 가리킵니다. 좁은 · 중간 · 넓은 범위는 범위를 가리킵니다. 큰 테스트와 넓은 범위 테스트는 이름이 닮았어도 서로 다른 축의 말입니다.
무엇을 진짜로 띄우나
넓은 범위 테스트를 돌리려면 검사할 부분들을 전부 띄워야 합니다. 운영 중인 서버에서 돌리면 진짜 사용자의 데이터가 섞입니다. 그래서 운영과 같은 모양으로 꾸린 시험용 환경을 따로 둡니다. 이 환경이 스테이징 환경입니다.
모든 부분을 진짜로 둘 수는 없습니다. 결제 서비스는 우리 시스템의 일부라 진짜를 띄웁니다. 그런데 결제 서비스는 돈을 옮기려고 바깥 결제 회사를 다시 부릅니다. 이 호출은 부를 때마다 진짜 돈이 오갑니다.
그래서 바깥 결제 회사만 진짜처럼 답하는 목 서버로 바꿔 끼웁니다. 앞에서 본 userId 와 memberId 어긋남은 주문 서비스와 결제 서비스 사이의 일입니다. 그래서 이렇게 바꿔 끼워도 드러납니다.
진짜로 둔 부분이 많을수록 운영에서 겪을 일에 가까운 확인이 됩니다. 가짜가 늘수록 테스트는 가벼워집니다. 대신 그 가짜를 만든 사람의 짐작만큼만 믿을 수 있습니다. 그래서 넓은 범위 테스트를 짤 때는 어디까지 진짜로 둘지부터 정합니다.
넓을수록 치르는 값
넓은 범위 테스트는 느립니다. 여러 부분을 띄우고, 한 흐름 안에서 네트워크를 여러 번 건너기 때문입니다. 한 건이 도는 동안 좁은 범위 테스트는 훨씬 많이 끝납니다.
결과가 흔들리기도 쉽습니다. 네트워크 지연, 떠 있는 서비스의 상태, 앞 테스트가 남긴 데이터처럼 코드 밖의 것을 많이 품기 때문입니다. 코드가 그대로인데 돌릴 때마다 결과가 달라지는 테스트를 불안정한 테스트라고 부릅니다.
깨졌을 때 원인을 찾기도 어렵습니다. 알 수 있는 것은 「주문이 끝나지 않았다」 하나입니다. 원인은 주문 · 재고 · 결제 코드일 수도, 설정 하나일 수도 있습니다. 서비스마다 남긴 로그를 따라가며 어느 연결에서 끊겼는지 좁혀 들어갑니다.
얼마나 두나
이런 값 때문에 넓은 범위 테스트는 적게 둡니다. 흔한 권장은 좁은 범위 테스트를 가장 많이, 넓은 범위 테스트를 가장 적게 두는 것입니다. 범위별 개수를 좁은 범위부터 아래에서 위로 쌓으면 아래가 넓은 모양이 됩니다. 이 모양을 테스트 피라미드라고 부릅니다.
구글은 대략 좁은 범위 80%, 중간 범위 15%, 넓은 범위 5%를 목표로 둡니다. 비즈니스 논리 대부분은 좁은 범위 테스트가 맡는다는 뜻입니다.
거꾸로 된 모양에도 이름이 있습니다. 넓은 범위 테스트가 가장 많고 좁은 범위 테스트가 적은 모양을 아이스크림 콘이라고 부릅니다. 이런 테스트 묶음은 느리고 자주 흔들립니다.
넓은 범위와 좁은 범위는 많은데 중간 범위가 빈 모양은 모래시계라고 부릅니다. 중간 범위 테스트로 일찍 잡을 수 있던 고장이 넓은 범위 테스트까지 가서야 걸립니다. 그만큼 고장을 늦게 압니다. 원인도 멀리서 찾아야 합니다.
넓은 범위 테스트가 맡는 일
넓은 범위 테스트는 좁은 범위로는 못 덮는 것에 씁니다. 가입, 로그인, 결제처럼 멈추면 사업이 멈추는 흐름이 첫째입니다. 서비스 사이의 약속이 맞는지도 이 테스트로 확인합니다.
설정 실수도 넓은 범위에서야 드러납니다. 접속 주소나 인증 키를 잘못 넣은 배포는 코드 검사를 전부 통과합니다. 시스템을 띄워 요청을 한 번 흘려 봐야 막힌 곳이 보입니다.
경우의 수가 많은 계산에는 맞지 않습니다. 할인 규칙이 스무 갈래면 넓은 범위 테스트도 스무 개가 필요합니다. 하나하나가 시스템 전체를 지나가느라 오래 걸립니다. 계산의 갈래는 좁은 범위 테스트로 검사합니다. 넓은 범위 테스트는 흐름마다 몇 개만 둡니다.
돌리는 시점
넓은 범위 테스트는 한 번 도는 데 오래 걸려서 코드를 고칠 때마다 전부 돌리기 어렵습니다. 지속적 통합은 누가 코드를 올릴 때마다 서버가 빌드하고 테스트를 돌려 주는 방식입니다. 이 흐름에서 넓은 범위 테스트는 대개 뒤쪽에 섭니다.
좁은 범위와 중간 범위 테스트가 먼저 돕니다. 그것들이 통과하면 스테이징 환경에 올려 넓은 범위 테스트를 돌립니다. 이 순서는 빨리 끝나는 검사로 흔한 고장을 먼저 거릅니다. 오래 걸리는 검사는 거기서 남은 것만 봅니다.
관련 항목
넓은 범위 테스트에 드는 테스트 이름
종단 간 테스트 · 시스템 테스트 · 기능 테스트 · 인수 테스트 · 스모크 테스트
범위로 넓은 범위 테스트와 나란히 서는 테스트
좁은 범위 테스트 · 중간 범위 테스트 · 단위 테스트 · 통합 테스트 · 컴포넌트 테스트 · 계약 테스트
테스트를 범위 · 크기 · 개수로 가르는 분류
테스트 범위 · 테스트 크기 · 작은 테스트 · 중간 테스트 · 큰 테스트 · 테스트 피라미드 · 테스팅 트로피 · 아이스크림 콘 안티패턴
넓은 범위 테스트가 진짜 대신 끼우는 가짜
테스트 더블 · 목 서버 · 스텁 · 페이크 · 인메모리 데이터베이스
넓은 범위 테스트에서 자주 나는 문제
불안정한 테스트 · 깨지기 쉬운 테스트 · 테스트 데이터 오염 · 테스트 순서 의존성 · 타임아웃
넓은 범위 테스트가 도는 환경과 개발 단계
스테이징 환경 · 테스트 환경 · 지속적 통합 · 지속적 전달 · 배포 파이프라인 · 회귀 테스트
넓은 범위 테스트가 지나가는 시스템 부분
마이크로서비스 · API · HTTP · 데이터베이스 · 메시지 큐 · 결제 게이트웨이
깨진 넓은 범위 테스트의 원인을 좁히는 기록
넓은 범위 테스트가 속하는 상위 분류
다른 이름: large-scoped test · large-scope test · broad-scoped test · large-scoped · 넓은 범위의 테스트 · 광범위 테스트