종단 간 테스트
고친 사람 github-actions[bot]
종단 간 테스트는 사용자가 하는 일을 처음부터 끝까지 똑같이 해 봅니다. 그렇게 해서 시스템 전체가 제대로 도는지 확인합니다. 화면에서 버튼을 누르는 데서 시작해 데이터베이스에 주문이 남는 데까지 한 흐름을 끊지 않고 지나갑니다. 부분마다 검사를 마쳐도 전부 붙인 시스템이 사용자 앞에서 제대로 도는지는 따로 봐야 합니다. 그 마지막 확인을 맡는 검사입니다.
쉽고 빠른 이해
무슨 일을 하나 — 사람 대신 프로그램이 브라우저를 움직여 사용자 흉내를 냅니다. 로그인하고 상품을 담아 주문한 뒤 화면에 「주문 완료」가 뜨는지 보는 식입니다.
왜 하나 — 부분만 검사하면 그 부분이 부르는 다른 부분을 가짜로 바꿔 끼웁니다. 화면과 서버와 데이터베이스를 전부 진짜로 이어야만 드러나는 고장이 있습니다.
어떻게 도나
- 운영과 닮은 시험용 환경에 시스템 전체를 띄웁니다
- 테스트 코드가 화면을 눌러 한 흐름을 끝까지 지나갑니다
- 사용자 눈에 보이는 결과가 기대와 같은지 확인합니다
대가 — 오래 걸립니다. 가끔 이유 없이 깨지기도 합니다. 깨지면 원인이 어느 부분에 있는지부터 찾아야 합니다.
언제 쓰나 — 가입·로그인·결제처럼 멈추면 안 되는 흐름 몇 개에만 씁니다. 경우가 많은 계산은 단위 테스트로 넘깁니다.
상세
이 절은 온라인 쇼핑몰 하나를 두고 종단 간 테스트를 봅니다. 사용자는 브라우저에서 로그인하고 상품을 장바구니에 담아 주문합니다. 그 뒤에는 요청을 받는 서버와 주문을 저장하는 데이터베이스가 있습니다. 결제는 바깥 회사가 운영하는 결제 서버가 맡습니다.
새 식당이 문을 열기 전날을 떠올려 봅시다. 직원 한 명이 손님처럼 문을 열고 들어와 식탁에 앉습니다. 주문하고 음식을 받고 계산을 마친 뒤 나갑니다. 칼과 불판은 따로 점검했어도 손님 한 명의 식사가 막힘없이 이어지는지는 이렇게 한 번 지나가 봐야 압니다.
종단 간 테스트는 시스템을 전부 띄워 놓고 사용자가 하는 동작을 바깥에서 흉내 냅니다. 「종단」은 흐름의 양 끝입니다. 한 끝은 사용자가 만지는 화면입니다. 다른 끝은 데이터가 마지막에 남는 저장소입니다.
영어 이름 End-to-End test 도 「끝에서 끝까지」라는 같은 뜻입니다. 줄여서 E2E(End-to-End) 테스트라고도 부릅니다.
부분 검사가 놓치는 고장
종단 간 테스트가 필요한 까닭은 부분 검사가 보는 범위에 있습니다. 부분 검사는 한 번에 보는 범위가 좁아서 좁은 테스트라고도 합니다. 이 소절은 좁은 테스트 둘이 가짜로 두는 것과 그 틈에서 나는 고장을 봅니다.
단위 테스트는 함수나 클래스 하나를 떼어 검사합니다. 그 조각이 부르는 다른 부분은 테스트 더블이라 부르는 가짜로 바꿔 끼웁니다. 가짜는 테스트를 쓴 사람이 짐작한 대로만 움직입니다.
통합 테스트는 부분 둘 이상을 진짜로 붙여 봅니다. 주문 코드를 진짜 데이터베이스에 붙여 주문을 저장하고 다시 읽는 식입니다. 붙이는 것은 몇 개뿐입니다. 나머지는 여전히 가짜입니다.
전부를 이었을 때만 나는 고장은 둘 다 못 봅니다. 화면이 보내는 요청 모양과 서버가 기다리는 모양이 어긋날 수 있습니다. 로그인했다는 표시가 결제 화면까지 이어지지 않아 사용자가 다시 로그인하라는 말을 볼 수도 있습니다. 부분마다 검사를 통과해도 이런 고장은 한 흐름을 끝까지 지나가야 드러납니다.
바깥에서만 들어가는 검사
종단 간 테스트는 시스템 안쪽 코드를 직접 부르지 않습니다. 사용자가 쓰는 입구로만 들어갑니다. 웹 서비스라면 입구는 브라우저 화면입니다.
확인도 사용자가 보는 것으로 합니다. 화면에 뜬 문구, 목록에 새로 생긴 줄, 바뀐 금액 같은 것입니다. 안쪽 구조를 모르는 채 입력과 결과만 보는 검사를 블랙박스 테스트라고 부릅니다.
안쪽을 안 보므로 내부 코드를 고쳐도 테스트는 그대로 둘 수 있습니다. 사용자가 보는 동작이 같으면 테스트도 계속 통과합니다.
테스트 하나가 지나가는 길
이 소절은 「로그인해서 상품 하나를 주문한다」는 테스트 하나를 따라갑니다. 테스트 코드는 브라우저 하나만 만집니다. 서버와 데이터베이스는 전부 진짜입니다.
sequenceDiagram
participant 테스트 코드
participant 브라우저
participant 서버
participant 데이터베이스
테스트 코드->>브라우저: 이메일·비밀번호 입력, 로그인 버튼 누름
브라우저->>서버: 로그인 요청
서버->>데이터베이스: 계정 확인
테스트 코드->>브라우저: 상품 담고 주문 버튼 누름
브라우저->>서버: 주문 요청
서버->>데이터베이스: 주문 저장
서버-->>브라우저: 주문 완료 화면
테스트 코드->>브라우저: 「주문 완료」 문구 확인
그림에서 테스트 코드의 화살표는 전부 브라우저로만 갑니다. 사람이 하는 일과 같습니다. 입력하고 누르고 화면을 읽습니다.
서버와 데이터베이스 사이의 화살표는 테스트가 만든 것이 아닙니다. 사용자가 버튼을 눌렀을 때 시스템이 원래 하는 일입니다. 마지막 확인이 통과하면 그 사이의 모든 연결이 한 번씩 제대로 이어졌다는 뜻이 됩니다.
브라우저를 움직이는 도구
사람 대신 브라우저를 움직이려면 브라우저 자동화 도구가 필요합니다. 테스트 코드가 이 도구에 「이 칸에 글자를 넣어라」「이 버튼을 눌러라」를 명령합니다. 도구는 명령을 받아 진짜 브라우저를 움직입니다. Selenium · Playwright · Cypress 가 이런 도구입니다.
테스트는 대개 헤드리스 브라우저로 돌립니다. 헤드리스 브라우저는 창을 화면에 그리지 않고 도는 브라우저입니다. 모니터가 없는 서버에서도 돌릴 수 있어서 씁니다.
화면이 없는 서버의 종단 간 테스트
화면 없이 요청만 받는 백엔드 서버에도 종단 간 테스트를 씁니다. 이때 입구는 API(Application Programming Interface, 프로그램끼리 부르는 약속된 창구)입니다. 테스트 코드가 HTTP(HyperText Transfer Protocol, 웹 요청을 주고받는 규칙) 요청을 바깥에서 보냅니다. 그 요청들로 한 흐름을 끝까지 지나갑니다.
주문 흐름이라면 가입 요청, 로그인 요청, 주문 요청을 차례로 보냅니다. 마지막에 주문 조회 요청을 보내 방금 넣은 주문이 돌아오는지 봅니다. 안쪽 코드를 부르지 않고 사용자가 쓰는 입구로만 들어간다는 점은 브라우저 쪽과 같습니다.
테스트가 도는 환경
종단 간 테스트는 시스템 전체가 떠 있어야 돕니다. 운영 서버에서 돌리면 진짜 사용자의 데이터가 섞입니다. 그래서 운영과 같은 모양으로 꾸린 시험용 환경을 따로 둡니다. 이런 환경을 스테이징 환경이라고 부릅니다.
바깥 회사의 서비스는 테스트마다 진짜로 부르기 어렵습니다. 결제라면 진짜 돈이 오가기 때문입니다. 결제 회사가 돈이 오가지 않는 시험용 창구를 따로 열어 두면 그곳에 붙입니다. 그런 창구가 없으면 결제 서버처럼 답하는 목 서버를 띄웁니다.
테스트가 쓸 데이터도 준비해야 합니다. 로그인할 계정과 주문할 상품이 있어야 흐름이 시작됩니다. 테스트마다 자기 계정과 상품을 새로 만들면 다른 테스트가 남긴 데이터에 흔들리지 않습니다.
기다리기에서 오는 흔들림
버튼을 누른 뒤 다음 화면이 뜨기까지는 시간이 걸립니다. 테스트가 기다리지 않고 바로 확인하면 아직 안 뜬 문구를 못 찾아 깨집니다. 코드는 멀쩡한데 테스트만 깨진 것입니다.
몇 초씩 무조건 쉬게 하면 이 문제가 줄어드는 듯 보입니다. 서버가 늦게 답한 날에는 그 몇 초로도 모자라 여전히 깨집니다. 금방 답한 날에는 남은 시간을 그냥 버립니다.
그래서 시간이 아니라 조건을 기다리게 합니다. 「주문 완료 문구가 뜰 때까지 기다리되, 정해 둔 시간이 지나면 실패로 친다」는 식입니다. 조건이 채워지는 순간 바로 다음으로 넘어갑니다.
돌릴 때마다 결과가 달라지는 테스트를 불안정한 테스트라고 부릅니다. 종단 간 테스트는 네트워크 지연, 화면 그리기, 남은 데이터처럼 흔들리는 것을 가장 많이 품습니다. 좁은 테스트보다 불안정해지기 쉬운 까닭입니다.
화면이 바뀌면 깨지는 테스트
테스트는 누를 버튼을 어떻게든 찾아야 합니다. 버튼에 적힌 글자나 화면 위의 위치로 찾을 수 있습니다. 그러면 디자인을 고쳐 글자나 위치가 바뀌는 순간 테스트가 버튼을 못 찾습니다.
기능은 멀쩡한데 테스트가 깨지는 상태를 깨지기 쉬운 테스트라고 부릅니다. 이를 줄이려고 화면 요소에 테스트만 쓰는 이름표를 따로 붙여 둡니다. 디자인이 바뀌어도 이름표가 남아 있으면 테스트는 계속 버튼을 찾습니다.
깨졌을 때 원인 찾기
종단 간 테스트가 깨지면 알 수 있는 것은 「주문 완료 문구가 안 떴다」 하나입니다. 원인은 화면 코드일 수도, 서버일 수도, 데이터베이스 설정일 수도 있습니다. 흐름 전체를 지나가는 만큼 의심할 곳도 전체입니다.
원인을 좁히려고 테스트가 깨진 순간의 기록을 남깁니다. 그때의 화면 캡처, 브라우저가 보낸 요청과 받은 응답, 서버 로그가 흔한 기록입니다. 이 기록을 보고 어느 연결에서 끊겼는지 찾아 들어갑니다.
다른 테스트와 나뉘는 선
테스트는 한 번에 얼마나 넓게 보느냐로 나뉩니다. 종단 간 테스트는 가장 넓게 봅니다.
| 종류 | 진짜로 붙이는 것 | 걸리는 시간 | 깨졌을 때 |
|---|---|---|---|
| 단위 테스트 | 없다. 부르는 다른 부분은 전부 가짜 | 가장 짧다 | 깨진 조각이 바로 나온다 |
| 통합 테스트 | 부분 둘 이상, 또는 부분과 데이터베이스 같은 바깥 | 중간 | 어느 연결인지 찾아야 한다 |
| 종단 간 테스트 | 화면부터 저장소까지 사용자가 쓰는 흐름 전체 | 가장 길다 | 원인이 어디든 있을 수 있다 |
표에서 볼 것은 「진짜로 붙이는 것」 열과 「깨졌을 때」 열이 함께 넓어진다는 점입니다. 진짜로 붙인 것이 많을수록 짐작대로만 움직이는 가짜가 줄어듭니다. 그만큼 사용자가 겪을 일에 가까운 확인이 됩니다. 대신 깨졌을 때 뒤져야 할 곳도 늘어납니다.
흔한 권장은 좁은 테스트일수록 많이 두는 것입니다. 단위 테스트를 가장 많이, 종단 간 테스트를 가장 적게 둡니다. 개수를 층으로 쌓으면 아래가 넓은 모양이 됩니다. 이 모양을 테스트 피라미드라고 부릅니다.
이름이 겹치는 두 테스트
시스템 테스트는 전부 붙인 시스템을 요구 사항 목록에 맞춰 검사하는 단계를 가리킵니다. 시스템 전체를 띄운다는 점이 같아서 종단 간 테스트와 섞어 부르는 팀이 많습니다. 둘은 무엇을 따라 검사하느냐에서 갈립니다. 시스템 테스트는 요구 사항 목록을 한 줄씩 확인합니다. 종단 간 테스트는 사용자 한 명이 지나가는 흐름을 처음부터 끝까지 따라갑니다.
인수 테스트는 소프트웨어를 만들어 달라고 맡긴 고객이나 기획자가 정한 합격 조건을 확인하는 검사입니다. 기획자가 「주문한 상품은 주문 내역에 바로 보여야 한다」를 조건으로 정했다면 그것을 확인하는 검사가 인수 테스트입니다. 이 이름은 검사 범위가 아니라 합격 조건을 누가 정했느냐로 붙습니다.
범위와 합격 조건은 서로 다른 기준입니다. 그래서 한 테스트가 두 이름을 함께 가질 수 있습니다. 가입부터 결제까지 지나가는 테스트가 기획자가 정한 조건을 확인하면 종단 간 테스트이면서 인수 테스트입니다.
돌리는 시점
종단 간 테스트는 한 번 도는 데 오래 걸립니다. 코드를 고칠 때마다 전부 돌리기는 어렵습니다.
지속적 통합은 누가 코드를 올릴 때마다 서버가 빌드하고 테스트를 돌려 주는 방식입니다. 이 흐름에서 종단 간 테스트는 대개 뒤쪽에 섭니다. 단위 테스트와 통합 테스트가 통과한 뒤 스테이징 환경에 올려서 돌립니다.
배포한 직후에 핵심 흐름만 훑는 스모크 테스트에도 종단 간 테스트 몇 개를 골라 씁니다. 새로 올린 서비스가 기본 동작이라도 하는지 빨리 보려는 검사입니다.
회귀 테스트는 코드를 고친 뒤 멀쩡하던 기능이 다시 망가지지 않았는지 확인하는 검사입니다. 고친 곳과 떨어진 기능이 함께 망가질 수 있어서 필요합니다. 이미 만든 종단 간 테스트를 남겨 두었다가 변경마다 다시 돌리면 이 노릇도 합니다.
잘 맞는 흐름과 덜 맞는 흐름
종단 간 테스트가 가장 값을 하는 곳은 멈추면 사업이 멈추는 흐름입니다. 가입, 로그인, 결제가 그렇습니다. 이 흐름들은 여러 부분을 한꺼번에 지나가서 좁은 테스트로는 다 못 덮습니다.
조건에 따라 답이 갈리는 계산에는 덜 맞습니다. 할인 규칙에 경우가 스무 개면 종단 간 테스트도 스무 개가 필요합니다. 하나하나가 시스템 전체를 지나가느라 오래 걸립니다.
계산은 단위 테스트로 경우마다 검사합니다. 종단 간 테스트는 핵심 흐름마다 몇 개만 둡니다. 두 테스트가 맡는 일을 이렇게 나눕니다.
관련 항목
종단 간 테스트와 범위로 나뉘는 테스트
단위 테스트 · 통합 테스트 · 컴포넌트 테스트 · 계약 테스트 · 시스템 테스트 · 인수 테스트 · 스모크 테스트 · 회귀 테스트
테스트를 범위와 개수로 가르는 분류
테스트 피라미드 · 좁은 범위 테스트 · 넓은 범위 테스트 · 블랙박스 테스트 · 화이트박스 테스트 · 기능 테스트
종단 간 테스트가 브라우저를 움직일 때 쓰는 도구
브라우저 자동화 · 헤드리스 브라우저 · Selenium · Playwright · Cypress · WebDriver
종단 간 테스트가 바깥 서비스 대신 끼우는 가짜
종단 간 테스트가 지나가는 시스템 부분
브라우저 · 프론트엔드 · 백엔드 · API · HTTP · 데이터베이스 · 결제 게이트웨이 · 세션
종단 간 테스트에서 자주 나는 문제
불안정한 테스트 · 깨지기 쉬운 테스트 · 테스트 순서 의존성 · 테스트 데이터 오염 · 타임아웃
종단 간 테스트가 돌아가는 개발 단계
지속적 통합 · 지속적 전달 · 배포 파이프라인 · 스테이징 환경 · 빌드
깨진 종단 간 테스트의 원인을 찾는 기록
「종단 간」이라는 이름을 함께 쓰는 네트워크 용어
종단 간 원칙 · 종단 간 암호화 · 종단 간 지연
종단 간 테스트가 속하는 상위 분류
다른 이름: E2E 테스트 · E2E test · end-to-end test · end-to-end testing · 엔드투엔드 테스트 · 종단간 테스트