사전 인수 테스트
개념

인수 테스트

gabury1고친 사람 github-actions[bot]

인수 테스트는 다 만든 소프트웨어를 넘겨받기 전에 약속한 대로 도는지 확인합니다. 코드가 어떻게 짜였는지는 보지 않습니다. 쓰는 사람이 바란 일이 실제로 되는지를 봅니다. 이 확인을 통과해야 그 기능을 다 만든 것으로 칩니다.

쉽고 빠른 이해

무슨 일을 하나 — 기능을 요청한 쪽의 눈으로 「이게 되면 다 된 것」을 확인합니다. 「5만 원 이상 주문에 가입 쿠폰을 쓰면 5천 원이 깎인다」를 직접 주문해 보고 확인하는 식입니다.

왜 하나 — 개발자가 요청을 잘못 알아들으면 개발자가 쓴 테스트도 같이 틀립니다. 테스트는 다 통과합니다. 그런데 요청한 쪽은 원한 것이 아니라고 말합니다. 요청한 쪽의 기준으로 따로 확인해야 이 어긋남이 출시 전에 드러납니다.

어떻게 도나

  1. 만들기 전에 「무엇이 되면 다 된 것인가」를 요청한 쪽과 함께 문장으로 적습니다
  2. 다 만든 시스템을 띄우고 그 문장대로 써 봅니다
  3. 문장이 전부 맞으면 넘겨받습니다. 하나라도 틀리면 돌려보냅니다

대가 — 시스템 전체를 띄워야 해서 오래 걸립니다. 화면이나 요청 모양이 바뀌면 요청을 보내는 테스트 코드도 따라 고쳐야 합니다. 그래서 가입·결제처럼 깨지면 바로 손해가 나는 흐름에만 몇 개 두고, 세세한 경우는 단위 테스트에 맡깁니다.

상세

이 절은 쇼핑몰의 쿠폰 기능 하나를 가지고 인수 테스트를 봅니다. 요청을 문장으로 적는 데서 시작합니다. 다음에 그 문장을 테스트 코드로 옮깁니다. 끝으로 그 테스트가 배포 전에 도는 단계를 봅니다.

새 집에 들어가기 전에 집주인과 함께 집을 한 바퀴 돕니다. 수도꼭지를 틀어 봅니다. 창문과 보일러도 하나씩 만져 봅니다. 벽 속 배관이 어떻게 깔렸는지는 묻지 않습니다. 계약서에 적힌 대로 살 수 있는지만 봅니다.

인수 테스트는 소프트웨어가 합의한 요구를 채우는지 확인해서 넘겨받을지를 정하는 테스트입니다. 쿠폰 기능이라면 「5만 원 이상 주문에 가입 쿠폰을 쓰면 5천 원이 깎인다」가 참인지를 직접 주문해 보고 확인합니다. 새 회원으로 5만 원어치를 담아 쿠폰을 넣어 봅니다. 결제 금액이 4만 5천 원으로 나오면 통과입니다.

이름의 「인수」는 함수에 넘기는 인수가 아닙니다. 물건을 넘겨받는다는 뜻의 인수(引受)입니다. 영어로는 acceptance test 라고 부릅니다. 받아들일지 말지를 가르는 테스트라는 뜻입니다.

코드를 확인하는 테스트는 따로 있습니다. 단위 테스트는 함수 하나나 클래스 하나를 떼어 내어 기대한 값이 나오는지 봅니다. 그 기대한 값을 정하는 사람은 개발자입니다.

개발자가 요청을 잘못 알아들었다면 코드와 테스트가 같이 틀립니다. 쿠폰을 4만 원부터 쓰게 짰다면 테스트도 4만 원 기준으로 쓰여 통과합니다. 요청한 쪽의 기준으로 한 번 더 확인해야 이런 어긋남이 출시 전에 드러납니다. 인수 테스트가 따로 있는 까닭입니다.

인수 조건

인수 테스트는 무엇을 확인할지부터 정해야 돌릴 수 있습니다. 그래서 기능을 만들기 전에 「이것이 되면 다 된 것」을 문장으로 적어 둡니다. 이 문장들을 인수 조건이라고 부릅니다. 개발자 혼자 정하지 않고 기능을 요청한 쪽과 함께 정합니다.

인수 조건은 요청한 쪽이 읽을 수 있는 말로 적습니다. 클래스 이름이나 테이블 이름은 나오지 않습니다. 그래야 요청한 쪽이 「내가 바란 것이 이것이 맞다」고 확인해 줄 수 있습니다.

조건 하나는 흔히 세 토막으로 적습니다. 주어진 상황, 하는 일, 기대하는 결과입니다. 영어로는 세 토막 앞에 Given(주어진 상황)·When(하는 일)·Then(기대하는 결과)을 붙여 적어서 Given-When-Then 꼴이라고 부릅니다. 쿠폰 기능의 조건 하나를 적으면 아래와 같습니다.

토막 쿠폰 기능의 조건
주어진 상황 가입 쿠폰을 가진 새 회원이 5만 원어치를 담았다
하는 일 쿠폰을 넣고 결제한다
기대하는 결과 결제 금액은 4만 5천 원이다

조건 하나가 경우 하나를 맡습니다. 4만 9천 원어치를 담았을 때 쿠폰이 안 먹히는 경우는 조건을 하나 더 적어 따로 확인합니다. 경계 바로 아래와 바로 위를 둘 다 적어 두면 「5만 원 이상」이 「5만 원 초과」로 잘못 짜인 것도 드러납니다.

사람이 확인하는 인수 테스트

인수 테스트는 누가 돌리느냐에 따라 두 갈래로 나뉩니다. 한쪽은 사람이 직접 써 보고 확인합니다. 다른 쪽은 확인을 코드로 짜 두고 기계가 돌립니다.

사람이 하는 쪽은 그 소프트웨어를 쓸 사람이나 기능을 요청한 담당자가 맡습니다. 이것을 사용자 인수 테스트(User Acceptance Testing, UAT)라고 부릅니다. 대개 출시 직전에 스테이징 환경에서 합니다. 스테이징 환경은 실제 사용자가 쓰는 운영 서버와 최대한 같게 꾸린 연습용 서버입니다.

외주로 만든 소프트웨어라면 이 확인이 납품을 받아들이는 절차가 됩니다. 발주한 쪽이 인수 조건을 하나씩 확인합니다. 전부 통과해야 넘겨받습니다.

사람의 눈은 기계가 못 보는 것을 잡습니다. 버튼을 찾기 어렵다거나 업무 순서와 화면 순서가 안 맞는 것이 그렇습니다. 대신 사람의 시간이 들어서 코드를 고칠 때마다 돌릴 수는 없습니다.

코드로 짜 둔 인수 테스트

인수 조건을 코드로 옮기면 기계가 되풀이해 돌릴 수 있습니다. 이것이 자동 인수 테스트입니다. 코드를 고칠 때마다 돌립니다. 전에 통과한 조건이 여전히 통과하는지를 매번 확인하는 셈입니다.

아래는 자바의 테스트 도구인 JUnit 으로 쿠폰 조건을 옮긴 테스트입니다. shop 은 테스트용으로 띄운 서버에 요청을 보내는 도우미 객체입니다. 요청은 HTTP(HyperText Transfer Protocol)로 보냅니다.

Java
@Test
void 오만원_이상이면_쿠폰으로_오천원_깎인다() {
    shop.signUp("kim");
    shop.addToCart("kim", "키보드", 50000);
    shop.applyCoupon("kim", "WELCOME");

    int paid = shop.pay("kim"); // 45000

    assertEquals(45000, paid);
}

테스트 안에 클래스 이름이나 테이블 이름이 없습니다. 가입·담기·쿠폰·결제라는 사용자의 동작만 있습니다. 위 인수 조건의 세 토막이 코드에서도 보입니다. 앞 두 줄(signUp·addToCart)이 주어진 상황, applyCoupon·pay 두 줄이 하는 일, 마지막 줄이 기대하는 결과입니다.

요청을 어떻게 보내는지는 shop 이 맡습니다. 요청 주소나 화면 모양이 바뀌면 shop 만 고치면 됩니다. 테스트 본문은 인수 조건이 바뀔 때만 바뀝니다.

이렇게 시스템 속을 모르는 채로 바깥에서 입력을 넣고 결과만 보는 방식을 블랙박스 테스트라고 부릅니다. 인수 테스트는 이 방식을 따릅니다. 안쪽 구조를 바꿔도 요청한 쪽이 보는 동작이 같으면 테스트는 계속 통과합니다.

통과한 인수 테스트는 지우지 않고 남겨 둡니다. 나중에 다른 기능을 고치다 쿠폰이 깨지면 이 테스트가 잡습니다. 이미 되던 기능이 다시 안 되는지를 보는 이 쓰임이 회귀 테스트입니다.

배포 파이프라인 속 인수 테스트

코드로 짠 인수 테스트는 흔히 배포 파이프라인 안에서 돕니다. 배포 파이프라인은 커밋 하나가 운영 서버에 나가기까지 거치는 검사 단계를 자동으로 이어 둔 것입니다. 앞 단계를 통과해야 다음 단계로 넘어갑니다.

flowchart TD
    A["커밋"] --> B["빌드 · 단위 테스트"]
    B --> C["인수 테스트"]
    C --> D["스테이징 환경에서 확인"]
    D --> E["운영 배포"]

빌드는 소스 코드를 실행할 수 있는 파일로 묶는 단계입니다. 단위 테스트는 몇 분 안에 끝나서 빌드와 함께 맨 앞에 둡니다. 여기서 깨지면 뒤 단계는 돌리지 않습니다.

인수 테스트는 서버와 데이터베이스를 띄워야 해서 단위 테스트보다 오래 걸립니다. 그래서 단위 테스트를 통과한 버전에만 돌립니다.

인수 테스트를 통과한 버전은 스테이징 환경에 올려 한 번 더 확인한 뒤 운영 서버로 나갑니다. 앞 절의 사용자 인수 테스트를 사람이 돌리는 곳도 대개 이 스테이징 환경입니다.

인수 테스트를 통과한 버전은 언제든 내보낼 수 있는 후보가 됩니다. 마지막 배포를 사람이 버튼으로 고르는 방식이 지속적 전달입니다. 통과한 버전을 전부 자동으로 내보내는 방식은 지속적 배포입니다. 어느 쪽이든 「요청한 대로 된다」를 사람 대신 확인하는 단계를 인수 테스트가 맡습니다.

다른 테스트와 나뉘는 선

테스트 이름은 두 가지 기준으로 붙습니다. 하나는 한 번에 보는 범위입니다. 다른 하나는 확인하려는 목적입니다. 인수 테스트는 목적으로 붙은 이름입니다.

이름 붙은 기준 확인하는 것 기대한 값을 정하는 사람
단위 테스트 범위 조각 하나가 기대한 값을 내나 개발자
통합 테스트 범위 조각 여럿을 붙인 곳이 맞물리나 개발자
종단 간 테스트 범위 사용자 흐름이 처음부터 끝까지 이어지나 개발자나 테스터
인수 테스트 목적 합의한 요구를 채웠나 요청한 쪽과 개발자가 함께

기준이 달라서 한 테스트가 두 이름을 같이 가질 수 있습니다. 쿠폰 테스트는 가입부터 결제까지 시스템 전체를 지나므로 종단 간 테스트이기도 합니다. 가르는 질문은 하나입니다. 기대한 값이 요청한 쪽의 문장에서 나왔는지, 개발자의 설계에서 나왔는지입니다.

인수 테스트를 먼저 쓰는 방식

인수 조건을 기능보다 먼저 테스트로 옮겨 두는 방식도 있습니다. 처음에는 기능이 없으니 테스트가 실패합니다. 개발자는 이 테스트가 통과할 때까지 기능을 만듭니다. 이 방식을 인수 테스트 주도 개발(Acceptance Test-Driven Development, ATDD)이라고 부릅니다.

행위 주도 개발(Behavior-Driven Development, BDD)은 앞의 ATDD와 거의 같은 방식을 부르는 다른 이름으로 흔히 쓰입니다. Given-When-Then 문장을 요청한 쪽과 함께 적습니다. 그 문장을 그대로 테스트로 실행해 주는 도구를 씁니다.

두 방식 모두 「다 됐다」의 기준을 코드보다 먼저 합의해 두려는 것입니다. 기준이 먼저 있으면 개발자가 요청을 잘못 알아들은 것이 만들기 전에 드러납니다.

인수 테스트에 드는 비용

인수 테스트 하나는 단위 테스트 하나보다 오래 걸립니다. 서버와 데이터베이스를 띄우고 요청을 여러 번 오가야 하기 때문입니다. 수백 개가 쌓이면 한 번 돌리는 데 몇십 분이 걸리기도 합니다.

결과가 흔들리기도 합니다. 네트워크가 잠깐 늦거나 앞 테스트가 남긴 데이터가 있으면, 코드를 하나도 안 고쳤는데도 통과와 실패가 오갑니다. 이런 테스트를 불안정한 테스트라고 부릅니다. 불안정한 테스트가 쌓이면 사람들이 실패를 보고도 다시 돌려 보기만 하게 됩니다.

그래서 인수 테스트는 사업에 중요한 흐름에 몰아 둡니다. 가입, 결제, 환불처럼 깨지면 바로 손해가 나는 흐름이 그렇습니다. 경우를 하나하나 덮는 일은 단위 테스트에 맡깁니다. 쿠폰 금액 계산의 여러 경우는 단위 테스트로 봅니다. 쿠폰이 결제까지 이어지는지는 인수 테스트 몇 개로 봅니다.

관련 항목

인수 테스트와 확인하는 범위가 다른 테스트

단위 테스트 · 통합 테스트 · 시스템 테스트 · 종단 간 테스트 · 스모크 테스트 · 회귀 테스트

인수 테스트의 하위 종류

UAT · 운영 인수 테스트 · 계약 인수 테스트 · 규정 인수 테스트 · 베타 테스트

인수 테스트가 확인할 기준을 적는 방식

인수 조건 · 사용자 스토리 · 요구사항 · Given-When-Then · 완료의 정의 · 실행 가능한 명세

인수 테스트를 코드보다 먼저 쓰는 개발 방식

인수 테스트 주도 개발 · 행위 주도 개발 · 테스트 주도 개발

인수 테스트를 짜고 돌리는 도구

JUnit · Cucumber · Selenium · Playwright · FitNesse · REST Assured

인수 테스트가 한 단계를 맡는 배포 흐름

배포 파이프라인 · 지속적 통합 · 지속적 전달 · 지속적 배포 · 스테이징 환경 · 빌드 · 릴리스

인수 테스트가 시스템을 들여다보는 방식

블랙박스 테스트 · 화이트박스 테스트 · 그레이박스 테스트

인수 테스트에서 자주 나는 문제

불안정한 테스트 · 깨지기 쉬운 테스트 · 테스트 순서 의존성

인수 테스트가 속하는 상위 분류

QA와 테스트 · 소프트웨어 테스트 · 자동 테스트 · 품질 보증

다른 이름: acceptance test · acceptance testing · 인수 시험 · 승인 테스트 · 수용 테스트