본문으로 건너뛰기
중급약 25분

TC 설계 종합 — 입력·처리·출력 관점, 중복과 누락 줄이기

이 모듈에서 배운 기법들을 한 기능에 실제로 조합해보고, 입력·처리·출력 세 관점으로 빠진 부분을, 그리고 중복된 케이스를 정리한다.

  • #TC설계
  • #테스트케이스
  • #종합
  • #테스트설계

개념

이 모듈에서 여덟 개의 기법을 배웠다. 실무에서는 이 기법들을 하나만 골라 쓰지 않고 한 기능에 여러 기법을 겹쳐서 적용한다. 이 마지막 레슨은 그 조합을 실제로 해보고, 결과물(테스트 케이스 목록)에서 중복과 누락을 정리하는 법을 다룬다.

종합이란 기법을 나열하는 게 아니다

"기법을 조합한다"는 말을 처음 들으면 여덟 개 기법을 차례로 한 번씩 적용하는 것으로 오해하기 쉽다. 그렇게 하면 케이스는 많아지지만 같은 것을 여러 번 확인하는 목록이 나온다. 종합의 목적은 정반대다 — 가능한 한 적은 수의 케이스로 가능한 한 넓은 영역을 덮는 것이다.

병원을 떠올리면 이해가 빠르다. 의사는 환자 한 명에게 가진 검사 장비를 전부 돌리지 않는다. 문진으로 대략의 방향을 잡고, 그 방향에 맞는 검사를 고르고, 검사 결과가 애매하면 그때 다른 검사를 추가한다. 검사 목록이 아니라 진단 과정이 있는 것이다. 테스트 설계도 같다. 기능을 먼저 읽고, 그 기능에서 위험이 큰 축을 찾고, 그 축에 맞는 기법을 고른다.

기법을 나열하는 사람기법을 종합하는 사람
시작"어떤 기법을 쓸까?""이 기능에서 무엇이 잘못될 수 있지?"
결과물기법별로 나뉜 케이스 묶음기능 흐름 순서로 정렬된 하나의 목록
케이스 수많다 (중복 포함)적다 (겹치는 것이 정리됨)
리뷰에서"왜 이렇게 많아요?""이건 왜 없어요?"에 근거로 답함
빠진 것안 쓴 기법이 덮던 영역이 통째로 빔커버리지 점검으로 빈칸이 드러남

마지막 줄이 이 레슨의 두 축 — 중복 줄이기 와 누락 줄이기 — 이다.

입력·처리·출력(IPO) 관점

테스트 케이스를 짤 때 입력(Input)만 보고 끝내는 경우가 실무에서 가장 흔한 누락이다. 세 관점을 모두 확인하는 습관이 필요하다.

관점확인할 것예시 질문자주 쓰는 기법
입력어떤 값이 들어오는가유효한 값, 경계값, 비유효값을 다 다뤘는가?동등분할, 경계값 분석, 분류 트리
처리시스템 내부에서 무슨 일이 일어나는가계산 로직, 상태 변경, 외부 시스템 호출이 있는가?결정 테이블, 상태전이, 구조 기반
출력결과가 어떻게 나타나는가화면 표시, 알림, 로그, DB 저장까지 확인했는가?유즈케이스, 오류 추정

입력만 테스트하고 "정상적으로 처리됐겠지"라고 넘어가면, 계산이 틀렸거나 DB에 잘못 저장되는 결함을 놓친다. 반대로 출력(화면)만 보고 처리 로직을 안 보면, 화면엔 맞게 보이지만 실제 저장된 데이터는 틀린 경우(예: 화면엔 할인가가 보이지만 실제 결제 금액은 정가로 청구)를 놓친다.

출력 관점이 특히 자주 빠진다. 출력은 화면 하나가 아니기 때문이다. 하나의 입력이 들어가면 대개 여러 곳에 결과가 남는다.

출력이 남는 곳놓치면 생기는 일
화면표시 자체가 틀림 — 그나마 가장 빨리 발견된다
DB화면은 맞는데 저장값이 다름. 정산·통계가 조용히 틀어진다
외부 시스템(PG·배송사)우리 화면엔 할인가, 결제사엔 정가가 넘어간다
알림(메일·푸시·SMS)주문 완료 메일에만 옛 금액이 찍힌다
로그·분석 이벤트사후 분석과 CS 대응이 불가능해진다

한 기능의 테스트 케이스를 다 짠 뒤, 이 표를 보며 "내 케이스가 이 다섯 줄 중 몇 줄을 확인하고 있나"를 세어보면 누락이 바로 드러난다.

사례 연구 — "쿠폰 적용" 하나를 끝까지

이제 실제로 해보자. 아래 명세 하나를 이 모듈에서 배운 기법으로 처음부터 끝까지 관통한다. 각 단계에서 어떤 기법을 왜 골랐는지를 같이 따라가는 게 핵심이다.

쿠폰 적용 기능 명세

  1. 결제 화면에서 쿠폰 코드를 직접 입력하거나 보유 쿠폰 목록에서 선택한다.
  2. 쿠폰 코드는 영문 대문자와 숫자로 이루어진 8자리 다.
  3. 정률 쿠폰: 주문 금액 30,000원 이상일 때 10% 할인, 최대 할인 5,000원.
  4. 정액 쿠폰: 3,000원 할인, 최소 주문 금액 조건 없음.
  5. 한 주문에 쿠폰은 1장만 적용된다.
  6. 만료된 쿠폰·이미 사용한 쿠폰은 적용되지 않고 사유 메시지를 표시한다.
  7. 쿠폰 적용 후 상품을 빼서 최소 주문 금액 아래로 내려가면 쿠폰이 자동 해제된다.

1단계 — 입력 관점: 동등분할과 경계값

레슨 1에서 배운 동등분할 로 먼저 입력을 파티션으로 나눈다. 입력이 두 가지(쿠폰 코드, 주문 금액)이므로 각각 나눈다.

입력파티션대표값
쿠폰 코드유효(존재·미만료·미사용)SUMMER10
만료된 코드EXPIRE01
이미 사용한 코드USEDCODE
존재하지 않는 코드ZZZZ9999
형식 위반(소문자·특수문자·길이)summer10, SUM@ER1
빈 값(미입력)
주문 금액최소 조건 미만20,000원
최소 조건 이상, 한도 미만40,000원
한도 초과80,000원

파티션이 정해졌으면 레슨 1의 경계값 분석 으로 각 경계 양옆을 집는다. 여기서 초보자가 자주 놓치는 것이 경계가 두 개라는 사실이다.

경계근거뽑을 값
최소 주문 금액 30,000원명세 3항 "30,000원 이상"29,999 / 30,000 / 30,001
최대 할인 5,000원10%가 정확히 5,000원이 되는 금액 = 50,000원49,999 / 50,000 / 50,001
코드 길이 8자명세 2항 "8자리"7자 / 8자 / 9자

두 번째 줄이 진짜 핵심이다. "최대 할인 5,000원"이라는 문장에는 숫자 50,000원이 어디에도 안 적혀 있다. 명세에 적힌 숫자만 경계로 뽑으면 이 경계는 통째로 빠진다. 계산식(금액 × 10%)이 상한(5,000원)에 닿는 지점을 스스로 계산해내야 나오는 경계다. 명세에 없는 경계는 계산에서 나온다 — 이 습관 하나가 경계값 분석의 수준을 가른다.

2단계 — 처리 관점: 결정 테이블

입력 조합이 결과를 어떻게 가르는지는 레슨 3의 결정 테이블 이 가장 잘 보여준다. 조건을 세 개로 잡는다.

조건 \ 규칙R1R2R3R4R5
쿠폰이 유효한가YYYN(만료)N(사용됨)
쿠폰 종류정률정률정액--
주문금액 ≥ 30,000YNN--
결과10% 할인(최대 5,000)미적용 + 최소금액 안내3,000원 할인미적용 + 만료 안내미적용 + 사용됨 안내

이 표를 만드는 것만으로 얻는 게 두 가지 있다.

  • R3이 명세에서 놓치기 쉬운 규칙이다. 정액 쿠폰은 최소 금액 조건이 없으므로 20,000원 주문에도 적용된다. 정률 쿠폰의 30,000원 조건을 "쿠폰 전체의 조건"으로 잘못 읽으면 이 케이스는 아예 만들어지지 않는다.
  • R2·R4·R5의 결과가 전부 "미적용"이지만 안내 문구가 다르다. 결정 테이블의 결과 행을 "미적용"으로만 적어두면 세 케이스가 중복처럼 보인다. 결과를 문구까지 적어야 서로 다른 케이스임이 드러난다.

3단계 — 처리 관점: 상태전이

명세 7항("적용 후 금액이 내려가면 자동 해제")은 결정 테이블로 표현되지 않는다. 시간에 따라 상태가 변하는 규칙 이기 때문이다. 여기서 레슨 3의 상태전이 가 필요하다.

현재 상태이벤트다음 상태확인할 것
미적용유효 쿠폰 적용적용됨할인 금액이 즉시 반영되는가
적용됨사용자가 직접 해제미적용쿠폰이 보유 목록으로 되돌아오는가
적용됨상품 삭제로 금액 하락자동 해제안내 없이 조용히 풀리지 않는가
적용됨주문 확정사용 완료쿠폰이 재사용 불가로 바뀌는가
사용 완료주문 취소복원 또는 소멸명세에 안 적혀 있다
사용 완료다시 적용 시도거부R5 안내가 나오는가

마지막에서 두 번째 줄이 이 단계의 수확이다. 주문을 취소하면 쿠폰이 돌아오는가? 명세 어디에도 답이 없다. 상태 표를 그리지 않았다면 이 질문은 떠오르지 않았을 것이고, 운영에서 CS 문의로 처음 발견됐을 것이다. 상태전이 표의 진짜 가치는 케이스를 만드는 것보다 표의 빈칸이 곧 명세의 빈칸임을 드러내는 것 에 있다. 모듈 2에서 배운 "요구사항의 빈틈을 질문으로 되돌리기"가 여기서 그대로 이어진다.

4단계 — 출력 관점: 결과가 남는 다섯 곳

같은 "30,000원 주문 + 정률 쿠폰" 하나를 놓고도 확인할 출력이 여러 개다. 레슨 4의 유즈케이스 기반 테스트 가 여기서 쓰인다 — 쿠폰 적용 하나가 아니라 장바구니 → 쿠폰 적용 → 결제 → 주문 완료 → 영수증 이라는 사용자 시나리오 전체를 따라가며 각 지점의 출력을 확인하는 것이다.

확인 지점기대 결과놓치면
결제 화면할인 -3,000원, 최종 27,000원 표시표시 오류
결제사로 넘어가는 금액27,000원화면은 할인가, 실제 청구는 정가
주문 DB의 결제 금액·쿠폰 id27,000 / 적용된 쿠폰 id 기록정산·매출 통계가 틀어짐
쿠폰 상태사용 완료로 변경같은 쿠폰 무한 재사용
주문 완료 메일할인 내역 포함, 27,000원고객 문의 발생

두 번째 줄이 이 기능에서 가장 비싼 결함이다. 화면만 보는 테스트로는 절대 발견되지 않고, 발견됐을 때는 이미 돈이 잘못 청구된 뒤다.

5단계 — 조합이 폭발할 때: 페어와이즈와 분류 트리

쿠폰은 혼자 동작하지 않는다. 회원 등급, 결제 수단, 배송 방식이 같이 얽힌다.

  • 쿠폰 종류 2가지 × 회원 등급 3가지 × 결제 수단 4가지 × 배송 2가지 = 48조합

전수 테스트는 불가능하다. 여기서 레슨 5의 페어와이즈 를 쓴다. 결함 대부분이 두 요인의 상호작용에서 나온다는 경험칙에 기대어, 모든 쌍을 한 번 이상 덮는 12개 안팎의 조합으로 줄인다. 48 → 12는 4분의 1이다.

다만 페어와이즈에는 넣으면 안 되는 조합이 섞여 나올 수 있다(예: "정액 쿠폰 + 주문금액 2,000원"은 할인액이 주문액보다 커진다). 이런 제약을 정리하고 축을 눈에 보이게 그리는 데 레슨 6의 분류 트리 가 유용하다. 쿠폰이라는 테스트 대상을 코드 형식 / 유효성 / 종류 / 주문 금액대 네 축으로 그려놓으면, 축 자체가 빠졌는지가 그림으로 보인다.

6단계 — 코드로 뒷받침하기: 구조 기반

여기까지는 전부 명세 기반이다. 명세에 없는 분기는 명세 기반 기법으로 절대 나오지 않는다. 레슨 7의 구조 기반(커버리지) 기법이 마지막 그물이다.

개발자가 짠 쿠폰 계산 함수의 분기 커버리지를 재봤더니 92%가 나왔고, 안 덮인 8%가 if (coupon.type === 'FIXED' && coupon.rate > 0) 라는 분기였다고 하자. 명세에는 없는 조건이다. 왜 있는지 물어보면 대개 셋 중 하나다 — 과거 정책의 잔재, 다른 팀 요청으로 몰래 들어간 예외, 또는 개발자의 방어 코드. 어느 쪽이든 테스트 케이스가 하나 더 필요하거나, 코드가 지워져야 한다.

커버리지는 "얼마나 했나"를 재는 점수가 아니라 "명세와 코드가 어긋난 곳을 찾는 탐지기" 로 쓸 때 가장 값지다.

7단계 — 마지막 그물: 경험 기반

레슨 8의 오류 추정 과 체크리스트로 마무리한다. 앞의 여섯 단계는 전부 "정해진 축"을 따라간 것이라, 축 바깥의 결함은 여전히 남아 있다.

  • 쿠폰 코드를 복사·붙여넣기 하면 앞뒤에 공백이 붙는다 — " SUMMER10 "
  • 브라우저 탭 두 개에서 같은 쿠폰을 동시에 적용하면?
  • 쿠폰 적용 후 뒤로가기 로 돌아왔다가 다시 결제하면 두 번 할인되나?
  • 만료 1분 전에 적용하고, 만료 후에 결제 버튼을 누르면?
  • 할인 계산 결과가 소수점이 되면(예: 33,333원의 10%) 반올림 방향은?

마지막 항목은 금액이 걸린 기능에서 거의 항상 문제가 된다. 반올림·내림 규칙이 명세에 없다면 그것 자체가 보고 대상이다.

종합된 최종 TC 목록

일곱 단계에서 나온 케이스를 하나의 목록으로 합치면 이렇게 된다. 표를 기법별로 나누지 않고 기능 흐름 순서로 정렬한 것에 주목하자.

TC조건기대 결과관점적용 기법
TC-01유효 코드 8자 입력정상 인식입력동등분할
TC-02코드 7자 / 9자형식 오류 안내입력경계값
TC-03소문자 코드 summer10정책대로 처리(대소문자 구분 여부 확인)입력동등분할
TC-04앞뒤 공백 포함 코드공백 제거 후 정상 인식입력오류 추정
TC-0529,999원 + 정률 쿠폰미적용 + 최소금액 안내처리경계값 + 결정테이블(R2)
TC-0630,000원 + 정률 쿠폰3,000원 할인처리경계값 + 결정테이블(R1)
TC-0749,999 / 50,000 / 50,001원할인 4,999 / 5,000 / 5,000처리경계값(계산에서 도출)
TC-0820,000원 + 정액 쿠폰3,000원 할인처리결정테이블(R3)
TC-09만료 쿠폰미적용 + 만료 안내처리결정테이블(R4)
TC-10사용 완료 쿠폰 재적용미적용 + 사용됨 안내처리결정테이블(R5) + 상태전이
TC-11적용 후 상품 삭제로 29,000원자동 해제 + 사용자 안내처리상태전이
TC-12주문 확정쿠폰 상태가 사용 완료로 변경처리상태전이
TC-13주문 취소명세 확인 필요 (복원/소멸)처리상태전이(빈칸 발견)
TC-1433,333원 + 정률 쿠폰반올림 규칙대로 계산처리오류 추정
TC-15정률 쿠폰 적용 결제결제사 전달 금액 = 할인가출력IPO(출력)
TC-16정률 쿠폰 적용 결제DB 결제금액·쿠폰 id 정확 기록출력IPO(출력)
TC-17정률 쿠폰 적용 결제주문 완료 메일에 할인 내역 포함출력유즈케이스
TC-18등급×결제수단×배송 조합 12건모든 조합에서 할인 정상처리페어와이즈
TC-19FIXED + rate > 0 쿠폰코드 분기 확인 (명세 외 분기)처리구조 기반
TC-20두 탭에서 동시 적용한쪽만 성공, 중복 할인 없음처리오류 추정

20개다. 아무 기법 없이 감으로 짜면 보통 68개가 나오고, 그 68개는 대부분 TC-01, TC-06, TC-09 같은 입력 관점의 정상·비정상에 몰려 있다. 기법 조합의 효과는 여기서 눈으로 확인된다.

중복을 판별하는 기준

케이스를 여러 기법으로 만들다 보면 같은 걸 다른 이름으로 두 번 확인하는 경우가 생긴다. 문제는 "비슷해 보인다"만으로는 지울지 말지 판단이 안 된다는 것이다. 판별 기준이 필요하다.

두 TC가 (가) 같은 파티션의 값을 쓰고 (나) 같은 코드 경로를 지나며 (다) 같은 것을 검증한다면 — 셋이 모두 참일 때만 중복이다.

셋 중 하나라도 다르면 남긴다. 실제로 판별해보자.

#TC ATC B파티션코드 경로검증 대상판정
130,000원 정률 쿠폰 → 할인 적용35,000원 정률 쿠폰 → 할인 적용같음(≥30,000)같음같음(할인 계산)중복 — 하나만 남긴다
229,999원 → 미적용30,000원 → 적용다름다름같음유지 — 경계 양옆이다
3만료 쿠폰 → 미적용사용된 쿠폰 → 미적용다름다름같음(문구는 다름)유지 — 안내 문구가 다르다
430,000원 → 화면에 27,000원 표시30,000원 → DB에 27,000 기록같음같음다름유지 — 출력 지점이 다르다
550,000원 → 할인 5,000원80,000원 → 할인 5,000원같음(한도 초과)같음같음중복 — 50,000원만 남긴다
6코드 7자 → 오류코드 9자 → 오류다름(양쪽 경계)같을 수 있음같음유지 — 경계는 양쪽을 본다

1번과 5번이 전형적인 중복이다. 둘 다 같은 파티션 안에서 대표값만 다른 케이스인데, 동등분할의 전제가 "한 파티션 안의 값은 같게 동작한다"이므로 두 개를 다 돌릴 이유가 없다.

3번과 4번을 남기는 이유가 특히 중요하다. 결과 칸의 글자가 같아 보인다고 중복이 아니다. 3번은 "미적용"으로만 적으면 똑같아 보이지만 서로 다른 분기를 지나고 서로 다른 문구를 낸다. 4번은 조건도 결과 금액도 같지만 확인하는 곳이 화면과 DB로 다르다 — 앞서 본 "화면은 할인가, 청구는 정가" 결함이 정확히 이 둘 사이에서 산다.

중복을 지울 때의 안전장치. 지우기 전에 "이 케이스만 실패하는 상황을 상상할 수 있는가"를 물어본다. 남긴 케이스는 통과하는데 지운 케이스만 실패하는 시나리오가 하나라도 떠오른다면, 그건 중복이 아니다.

누락을 찾아내는 체크리스트

케이스를 다 만든 뒤 "빠진 게 없나" 하고 눈으로 훑는 것은 거의 효과가 없다. 빠진 것은 원래 안 보이기 때문이다. 대신 축을 정해놓고 표의 빈칸을 찾는다. 두 개의 표를 쓴다.

첫 번째 — 기법 커버리지 표. 이 모듈에서 배운 기법을 세로로 놓고, 각 기법을 이 기능에 적용했는지 표시한다. "안 씀"에는 반드시 이유를 적는다.

기법적용?근거 / 안 쓴 이유
동등분할 (레슨 1)OTC-01, 03, 08
경계값 분석 (레슨 1)OTC-02, 05, 06, 07
상태전이 (레슨 3)OTC-11, 12, 13
결정 테이블 (레슨 3)OTC-05, 06, 08, 09, 10
유즈케이스 (레슨 4)OTC-17 (주문 완료까지의 흐름)
페어와이즈 (레슨 5)OTC-18
분류 트리 (레슨 6)△축 정리용으로만 사용, 별도 TC 없음
구조 기반 (레슨 7)OTC-19 (분기 커버리지 92% → 미커버 분기)
경험 기반 (레슨 8)OTC-04, 14, 20

이 표의 힘은 "O"가 아니라 "X"에 있다. "경계값은 확인했는데 상태전이는 안 했다"는 것이 한눈에 보인다. 그리고 X 옆에 이유를 적게 하면, 적으려다가 "어? 이 기능도 상태가 있는데?"를 스스로 깨닫는 일이 자주 생긴다. 이유를 못 적겠으면 그건 안 쓴 게 아니라 빠뜨린 것 이다.

두 번째 — IPO 커버리지 표. 앞의 출력 다섯 지점을 그대로 쓴다.

관점확인한 TC비었나
입력TC-01~04채워짐
처리 — 계산TC-05~08, 14채워짐
처리 — 상태TC-11~13채워짐
출력 — 화면TC-06채워짐
출력 — DBTC-16채워짐
출력 — 외부 시스템TC-15채워짐
출력 — 알림TC-17채워짐
출력 — 로그·분석없음빈칸

마지막 줄이 이 표를 그린 보상이다. 쿠폰 사용 로그가 안 남으면 나중에 "이 쿠폰이 얼마나 쓰였나"를 아무도 답할 수 없다. TC-21이 여기서 하나 더 나온다.

마지막으로, 표로 안 잡히는 것들은 질문 목록으로 훑는다.

  1. 정상 케이스뿐 아니라 예외·비정상 케이스도 있는가?
  2. 각 에러 상황마다 서로 다른 안내 문구를 확인하고 있는가?
  3. 되돌리기(취소·환불·해제) 경로가 있는가? 대개 정방향만 테스트한다
  4. 권한이 다른 사용자(비회원·타인 쿠폰·관리자)로도 확인했는가?
  5. 명세에 안 적혀 있어서 케이스를 못 만든 항목을 질문으로 남겼는가

5번이 중요하다. TC-13(주문 취소 시 쿠폰 복원)처럼 답을 모르는 것은 케이스를 지우는 게 아니라 "확인 필요"로 남겨둔 채 기획에 질문한다. 지우면 그 빈틈은 아무도 모르게 사라진다.

"적용 기법" 컬럼 — 설명 가능한 TC 문서

앞의 최종 TC 표에서 오른쪽 두 칸(관점, 적용 기법)을 눈여겨보자. 이 두 칸이 있고 없고가 리뷰 자리에서 만드는 차이는 생각보다 크다.

기법 컬럼이 없을 때기법 컬럼이 있을 때
"왜 이 케이스가 있나요?"기억을 더듬어 그때의 논리를 재구성"결정테이블 R4입니다"로 한 줄
"이거 중복 아닌가요?"감으로 방어하거나 그냥 지움"파티션이 다릅니다"로 근거 제시
"빠진 거 없나요?"답할 방법이 없음커버리지 표를 그대로 보여줌
6개월 뒤 유지보수처음부터 다시 설계명세가 바뀐 부분의 기법만 다시 적용
다른 사람이 인수인계케이스 목록만 물려받음설계 근거까지 물려받음

특히 마지막 줄이 실무에서 가장 크게 체감된다. 담당자가 바뀌면 기법 태그가 없는 TC 문서는 사실상 "누가 왜 만들었는지 모르는 목록"이 되고, 새 담당자는 손대기 무서워서 케이스를 지우지도 늘리지도 못한 채 그대로 돌린다. 그렇게 몇 년이 지나면 아무도 이유를 모르는 케이스 수백 개가 매 릴리즈마다 실행된다.

리뷰에서 실제로 쓰는 화법도 정리해두자. 모듈 2에서 배운 "질문으로 되돌리기"와 같은 원리로, 방어가 아니라 근거를 제시하는 방식이다.

지적이렇게 답한다
"케이스가 너무 많은데요""20개 중 12개가 결정테이블 5개 규칙과 경계 3쌍에서 나온 필수 케이스입니다. 줄인다면 페어와이즈 12건을 6건으로 줄이는 게 위험이 가장 적습니다."
"이 두 개 같은 거 아니에요?""조건은 같은데 하나는 화면, 하나는 DB 확인입니다. 실제로 이 둘이 갈리는 결함이 있었습니다."
"쿠폰 만료 케이스 없나요?""TC-09입니다. 결정테이블 R4에서 나왔습니다."
"이건 왜 확인 필요라고 되어 있죠?""상태전이 표를 그리다 보니 주문 취소 시 쿠폰 처리가 명세에 없어서요. 정해주시면 케이스로 확정하겠습니다."

세 번째와 네 번째 답변이 특히 중요하다. 셋째는 누락이 아님을 즉시 증명하고, 넷째는 누락의 책임을 QA가 아니라 미결정 사항으로 정확히 위치시킨다. 기법 태그 한 칸이 이 두 가지를 가능하게 한다.

이게 모듈 1(레슨 5)에서 강조한 설명 가능성 이 TC 문서 형태로 나타난 모습이다.

실무에서 왜 필요한가

"이 기능 테스트 케이스 짜보세요"는 면접과 실무 모두에서 QA에게 가장 자주 요구되는 실전 능력이다. 이때 평가받는 건 케이스의 개수가 아니라, 여러 기법을 목적에 맞게 조합했는지, 그리고 각 케이스의 존재 이유를 설명할 수 있는지다.

첫째, 리뷰 시간이 줄어든다. 기법 태그가 없는 TC 문서 리뷰는 케이스 하나하나를 놓고 "이게 필요한가"를 논의하느라 길어진다. 태그가 있으면 논의가 기법 단위로 올라간다 — "페어와이즈 12건은 6건으로 줄입시다"처럼. 20개 케이스를 하나씩 보는 것과 9개 기법 항목을 보는 것은 회의 길이가 다르다.

둘째, 테스트 범위를 협상할 수 있게 된다. 일정이 부족해서 케이스를 줄여야 할 때, 근거 없이 줄이면 무엇을 잃는지 아무도 모른다. 기법별로 묶여 있으면 "경계값과 결정테이블은 유지하고 페어와이즈만 절반으로 줄이면, 두 요인 상호작용 결함의 발견 확률이 떨어집니다"라고 잃는 것을 명시한 채 협상할 수 있다. 스테이지 2의 테스트 계획·리스크 기반 우선순위가 이 위에 올라간다.

셋째, 자동화 대상을 고를 때 그대로 재사용된다. 스테이지 4에서 "무엇부터 자동화할까"를 정할 때, 기법 태그가 곧 답이다. 결정 테이블과 경계값에서 나온 케이스는 입력·기대값이 명확해 자동화 비용이 가장 낮고 회귀 가치가 높다. 반대로 오류 추정에서 나온 케이스는 사람이 손으로 하는 게 낫다. 태그가 없으면 이 판단을 케이스마다 다시 해야 한다.

넷째, 명세의 빈틈이 테스트 설계 단계에서 드러난다. 이 레슨의 사례에서 TC-13(주문 취소 시 쿠폰 복원)과 TC-14(소수점 반올림)는 테스트를 실행하기 전에 발견됐다. 모듈 1에서 본 결함 수정 비용 곡선을 떠올리면, 이 둘을 설계 단계에서 질문으로 던지는 것과 운영에서 CS 문의로 받는 것의 비용 차이는 수십 배다. 테스트 설계는 결함을 찾는 활동이기 이전에 명세를 검증하는 활동이다.

신입 QA가 특히 얻는 것. 경력이 적을 때 가장 불안한 순간은 "제가 짠 케이스로 충분한가요?"라는 질문에 답할 수 없을 때다. 기법 커버리지 표는 이 불안을 절차로 바꿔준다. 충분함을 증명할 수는 없지만(모듈 1 — 테스트는 결함의 부재를 증명하지 못한다), 어떤 근거로 이만큼을 골랐는지는 언제나 말할 수 있게 된다.

실습 과제

과제 1 — 기법 조합해서 TC 작성하기 (20분)

"게시글 신고" 기능을 테스트한다고 하자 — "사용자는 게시글을 신고할 수 있고, 같은 게시글은 한 사용자당 한 번만 신고 가능하다. 신고가 5회 누적되면 게시글이 자동으로 숨김 처리된다." 이 기능에 대해 최소 3가지 다른 기법을 사용한 테스트 케이스를 6개 이상 작성하고, 각 케이스에 사용한 기법을 태그로 단다. 입력·처리·출력 세 관점을 모두 포함시킨다.

해설 보기

정답은 하나가 아니지만, 아래 축이 나왔는지 확인한다.

축나와야 할 케이스기법
누적 5회 경계4회 → 숨김 안 됨 / 5회 → 숨김 / 6회 → 상태 유지경계값
중복 신고같은 사용자가 같은 글을 두 번 신고 → 거부동등분할
상태 흐름숨김 처리된 글에 신고가 더 들어오면? 숨김 해제 후 카운트는?상태전이
신고 사유 입력사유 미선택 / 기타 사유 텍스트 길이 경계경계값
출력 — 화면신고 완료 안내가 뜨는가IPO(출력)
출력 — DB·관리자신고 기록이 남고 관리자 화면에 노출되는가IPO(출력)
출력 — 작성자숨김 처리 시 작성자에게 알림이 가는가유즈케이스
예외본인 글 신고 / 비로그인 신고 / 이미 삭제된 글 신고오류 추정

"5회 누적"에서 경계 3개(4·5·6)를 뽑았고, 상태전이를 떠올렸다면 성공이다. 가장 자주 빠지는 건 "숨김 해제 후 카운트가 초기화되는가"와 "작성자 알림"이다. 전자는 상태전이 표를 그려야 나오고, 후자는 출력 관점을 챙겨야 나온다.

과제 2 — 중복 찾기 (8분)

다음 테스트 케이스 목록에서 중복(같은 것을 두 번 확인하는 케이스)을 찾아 표시한다. 본문의 세 가지 판별 기준(파티션 / 코드 경로 / 검증 대상)을 적용한다.

  1. 재고 1개 남은 상품을 주문 → 성공
  2. 재고 1개 남은 상품을 주문 → 재고가 0으로 줄어드는지 DB 확인
  3. 재고 0개 상품을 주문 시도 → 실패
  4. 재고 1개 남은 상품을 정상 주문 → 주문 완료 화면 표시
해설 보기
파티션코드 경로검증 대상판정
1재고 ≥ 1주문 성공주문 성공 여부—
2재고 ≥ 1주문 성공DB 재고 차감유지
3재고 0주문 실패실패 처리유지
4재고 ≥ 1주문 성공화면 표시유지

1번이 중복이다. 1번의 "성공"은 4번의 "주문 완료 화면 표시"에 이미 포함되어 있다 — 파티션도 코드 경로도 검증 대상도 같다. 반면 2번과 4번은 조건이 같아도 확인하는 곳이 DB와 화면으로 다르므로 둘 다 남긴다.

여기서 반대로 놓치기 쉬운 것도 있다. 이 목록에는 재고 경계의 한쪽이 빠져 있다 — "재고 2개 이상"은 있어도 그만이지만, "마지막 1개를 두 사용자가 동시에 주문" 이 없다. 중복을 지우는 것보다 이 누락을 찾아낸 쪽이 훨씬 값진 발견이다.

과제 3 — 커버리지 표로 누락 찾기 (12분)

과제 1에서 만든 "게시글 신고" 케이스 목록에 본문의 기법 커버리지 표를 적용한다. 아홉 개 기법을 세로로 적고, 각각 O / △ / X를 표시하되 X에는 반드시 이유를 적는다.

이유를 적으려다 "어? 이것도 필요한데?"라고 생각이 바뀐 항목이 있다면, 그 항목이 이 과제의 진짜 수확이다. 그리고 IPO 커버리지 표도 같이 그려서 출력 다섯 지점(화면·DB·외부·알림·로그) 중 빈칸이 있는지 확인한다.

해설 보기

대부분의 사람이 이 과제에서 아래 두 가지를 새로 발견한다.

  • 페어와이즈 X — 처음엔 "조합할 축이 없다"고 적게 되는데, 적다 보면 신고 사유 종류 × 게시글 종류(텍스트/이미지/댓글) × 신고자 등급 같은 축이 있다는 걸 깨닫는다.
  • 로그 빈칸 — 신고 기록은 DB에 남지만, "누가 언제 왜 숨김 처리했는지"의 감사 로그(audit log)는 대개 아무도 확인하지 않는다. 신고·제재 기능에서는 이게 분쟁 대응의 유일한 근거라 특히 중요하다.

X에 이유를 적을 수 없다면 그건 안 쓴 게 아니라 빠뜨린 것 이라는 감각을 얻는 게 이 과제의 목적이다.

과제 4 — 리뷰 방어 연습 (10분)

과제 1에서 만든 TC 목록을 놓고, 아래 지적에 각각 한 문장으로 답해본다. 답에 반드시 기법 이름이나 커버리지 근거가 들어가야 한다.

  1. "케이스가 너무 많은 것 같은데, 절반으로 줄일 수 있나요?"
  2. "1번이랑 4번은 같은 거 아닌가요?"
  3. "신고 취소 케이스는 왜 없어요?"
  4. "이 기능 테스트, 얼마나 하면 충분한가요?"
해설 보기

4번이 가장 어렵고 가장 중요하다. "충분합니다"라고 답하면 안 된다 — 모듈 1에서 배웠듯 테스트는 결함의 부재를 증명하지 못한다. 대신 이렇게 답한다.

"충분하다고는 말씀드릴 수 없습니다. 다만 이 기능의 명세에 있는 규칙 전부와 누적 5회 경계, 상태 전이 네 가지를 덮었고, 안 덮은 영역은 동시성과 대량 신고 상황입니다. 그 둘까지 필요하면 이틀이 더 듭니다."

덮은 것 / 안 덮은 것 / 추가 비용 세 가지를 말하는 구조다. 이렇게 답하면 판단은 상대가 하게 되고, QA는 근거를 제공하는 사람이 된다. 이건 요구사항 리뷰에서 배운 "결정권은 넘긴다"와 정확히 같은 원리다.

자가 체크리스트

  • 입력·처리·출력(IPO) 세 관점을 구분하고, 각 관점에서 놓치기 쉬운 결함 유형을 설명할 수 있다
  • 출력이 남는 다섯 곳(화면·DB·외부 시스템·알림·로그)을 나열하고 각각의 케이스를 만들 수 있다
  • 한 기능에 여러 테스트 설계 기법을 조합해 테스트 케이스를 만들 수 있다
  • 명세에 숫자로 적혀 있지 않은 경계(계산에서 도출되는 경계)를 찾아낼 수 있다
  • 결정 테이블의 결과가 같아 보여도 안내 문구가 다르면 별개 케이스임을 설명할 수 있다
  • 상태전이 표의 빈칸이 곧 명세의 빈칸임을 알고, 질문으로 되돌릴 수 있다
  • 조합이 폭발할 때 페어와이즈로 줄이고, 분류 트리로 축을 정리할 수 있다
  • 구조 기반 커버리지를 "점수"가 아니라 "명세와 코드의 불일치 탐지기"로 쓸 수 있다
  • 중복 판별 세 기준(같은 파티션 / 같은 코드 경로 / 같은 검증 대상)을 적용할 수 있다
  • 중복을 지우기 전에 "이 케이스만 실패하는 상황"을 상상해보는 안전장치를 쓸 수 있다
  • 기법 커버리지 표를 그려 안 쓴 기법과 그 이유를 적어낼 수 있다
  • 각 테스트 케이스가 어떤 기법에서 나왔는지 태그를 달아 설명할 수 있다
  • 리뷰에서 "왜 이 케이스가 있나요"·"이거 중복 아닌가요"에 근거로 답할 수 있다
  • "얼마나 하면 충분한가요"에 덮은 것·안 덮은 것·추가 비용 구조로 답할 수 있다

흔한 실수

  • 입력값 검증에만 집중하고 처리·출력을 놓친다. 계산이 맞는지, 결과가 화면과 DB에 일관되게 반영되는지까지 봐야 완전한 테스트다. 특히 결제사 등 외부 시스템으로 넘어가는 값은 화면만 보면 절대 확인되지 않는다.
  • 출력을 화면 하나로만 생각한다. 알림 메일, 분석 로그, 관리자 화면도 출력이다. 로그가 빠지면 나중에 아무것도 추적할 수 없다.
  • 명세에 적힌 숫자만 경계로 뽑는다. "최대 할인 5,000원"에서 50,000원이라는 경계를 계산해내지 못하면 한도 로직은 통째로 미검증으로 남는다.
  • 케이스 개수를 늘리는 것 자체를 목표로 삼는다. 이 모듈 전체에서 반복 강조했듯, 중요한 건 각 케이스가 서로 다른 것을 검증한다는 근거이지 개수가 아니다.
  • 비슷해 보인다는 이유로 중복이라 판단해 지운다. 조건이 같아도 검증 대상이 다르면 중복이 아니다. 반대로 결과 문구가 달라 보여도 같은 파티션·같은 경로면 중복이다. 겉모습이 아니라 세 기준으로 판단한다.
  • 기법 태그 없이 케이스만 나열한다. 태그가 없으면 나중에 리뷰하거나 유지보수할 때 "이 케이스, 왜 있었지?"를 다시 처음부터 고민해야 한다. 담당자가 바뀌면 아무도 지우지도 늘리지도 못하는 목록이 된다.
  • "안 쓴 기법"에 이유를 안 적는다. 커버리지 표에서 X 옆이 비어 있으면 그건 판단한 게 아니라 빠뜨린 것이다.
  • 명세에 없어서 답을 모르는 케이스를 그냥 지운다. "주문 취소 시 쿠폰이 돌아오는가" 같은 항목은 삭제가 아니라 "확인 필요"로 남긴 채 질문해야 한다. 지우면 그 빈틈은 아무에게도 보이지 않게 된다.
  • 명세 기반 기법만으로 끝낸다. 명세에 없는 코드 분기는 명세 기반 기법으로 절대 나오지 않는다. 구조 기반과 경험 기반이 마지막 두 겹의 그물이다.
  • 정방향 흐름만 테스트한다. 취소·환불·해제·되돌리기 경로는 개발도 테스트도 가장 늦게 손대는 곳이라 결함이 몰려 있다.

참고 자료

  • Lee Copeland, A Practitioner's Guide to Software Test Design — 여러 기법을 조합하는 실무 전략을 다룬 챕터
  • ISTQB Foundation Level Syllabus — 이 모듈 전체에서 다룬 기법들의 공식 출처, 복습용으로 다시 참고
  • ISTQB Glossary — 동등분할·경계값·결정테이블 등 이 레슨에서 인용한 기법의 정확한 정의
  • Rex Black, Advanced Software Testing Vol. 1 — 기법 선택과 테스트 범위 협상을 테스트 분석가 관점에서 다룬다
  • Cem Kaner, "The Impossibility of Complete Testing" — "얼마나 하면 충분한가"에 왜 답할 수 없는지, 대신 무엇을 말해야 하는지의 고전적 근거

낯선 말 풀이

이 레슨에 나온 약어입니다. 본문에서도 처음 나올 때 점선으로 표시해 두었습니다 (제목과 링크 글자는 그대로 둡니다).

DB — 데이터베이스
데이터를 넣어 두고 꺼내 쓰는 저장소. 보통 표 여러 개가 서로 연결된 형태다.
PG — 결제 대행
쇼핑몰과 카드사 사이에서 결제를 중개해 주는 서비스.
SMS — 문자 메시지
휴대전화 문자.
CS — 고객 지원 · 칩 선택 신호
이 커리큘럼에서 두 가지로 쓰인다. ① 고객 문의와 불만을 직접 받는 조직 ② 여러 부품이 한 선을 나눠 쓸 때 "지금은 네 차례" 라고 하나를 고르는 신호. 앞뒤에 문의·고객이 있으면 ①, 통신·배선 이야기면 ②다.
TC — 테스트 케이스
무엇을 어떻게 해보고 무엇이 나와야 하는지를 한 건으로 적어 둔 것. 시험 문제 한 문항에 해당한다.
QA — 품질보증
만든 것이 쓸 만한지 확인하고, 애초에 덜 망가지게 만드는 방법을 정하는 일. "테스트"는 그 일의 일부다.
ISTQB — 국제 소프트웨어 테스팅 자격 위원회
테스터 자격 시험을 만들고 용어를 정리하는 국제 단체.

용어집 전체 보기

이 레슨의 실습

실습은 별도 저장소에서 진행합니다. 새 탭으로 열립니다.