본문으로 건너뛰기
입문약 20분

테스트 레벨 — 단위·통합·시스템·인수

같은 기능도 어느 레벨에서 테스트하느냐에 따라 다른 결함이 드러난다. 네 레벨이 각각 무엇을 확인하는지 구분하고, 어느 레벨에 투자할지 판단하는 기준을 익힌다.

  • #테스트레벨
  • #단위테스트
  • #통합테스트
  • #시스템테스트
  • #인수테스트

개념

공장에서 자동차를 검사하는 순서

자동차 공장을 떠올려보자. 완성된 차를 도로에 몰아보는 것만으로 품질을 보증하지는 않는다. 순서가 있다.

  1. 부품 하나씩 — 브레이크 패드 하나가 규격대로 마찰력을 내는가
  2. 부품을 맞물려서 — 브레이크 패드와 디스크가 서로 맞물려 도는가
  3. 완성차로 — 시속 100km에서 밟았을 때 실제로 서는가
  4. 고객이 타보고 — 이 브레이크의 밟는 느낌이 받아들일 만한가

부품 검사에서 걸러낼 수 있는 불량을 굳이 완성차 주행 시험까지 끌고 가면, 비용은 수백 배가 되고 원인을 찾는 데도 훨씬 오래 걸린다. 반대로 부품이 전부 규격에 맞아도 조립하면 안 맞을 수 있고, 조립이 완벽해도 고객이 싫어할 수 있다. 어느 한 단계도 다른 단계를 대신하지 못한다.

소프트웨어 테스트 레벨이 정확히 이 구조다. 테스트 레벨은 "무엇을 대상으로, 어느 범위까지 함께 실행해서" 확인하는가를 기준으로 나눈다. 범위가 좁을수록(단위) 빠르고 싸고, 넓을수록(인수) 느리고 비싸지만 더 현실에 가까운 조건을 본다.

레벨확인 대상보통 누가속도·비용
단위(Unit)함수·클래스 하나가 격리된 상태에서 맞게 동작하는가개발자매우 빠름·저렴
통합(Integration)두 개 이상의 모듈·서비스가 서로 맞물려 동작하는가개발자, QA빠름·중간
시스템(System)전체 애플리케이션이 엔드투엔드로 요구사항대로 동작하는가QA느림·비쌈
인수(Acceptance)실제 사용자·발주자 관점에서 받아들일 만한가QA, 사용자, 발주자가장 느림·비쌈

레슨 1에서 배운 결함 발견 시점별 비용이 여기서 다시 나타난다. 레벨은 개발 흐름의 시간 순서와 대체로 겹치기 때문에, 아래 레벨에서 잡는다는 건 곧 이르게 잡는다는 뜻이다.

같은 버그, 다른 레벨에서 다르게 보인다

"주문 금액 30,000원 이상이면 무료배송"이라는 기능을 예로 들어본다.

  • 단위: calculateShippingFee(30000) 함수 하나만 떼어서 0을 반환하는지 확인. 다른 함수·DB·네트워크는 전혀 관여하지 않는다.
  • 통합: 장바구니 모듈이 계산한 금액이 배송비 모듈에 정확히 전달되는지 확인. 두 모듈은 각자 단위 테스트를 통과했어도, 금액을 "원" 단위로 주고받기로 한 약속을 한쪽이 "센트"로 착각하면 통합 단계에서만 드러난다.
  • 시스템: 로그인 → 상품 담기 → 결제까지 전체 흐름에서 무료배송이 실제로 적용되는지 확인. 프론트엔드가 계산 결과를 화면에 제대로 반영하는지까지 포함된다.
  • 인수: 실제 사용자가 "이 조건이 헷갈리지 않고 명확한가"까지 포함해서 받아들일 만한 경험인지 확인. "30,000원 이상"이 배송비 제외 금액인지 포함 금액인지가 헷갈린다면, 계산은 다 맞아도 인수 단계에서 문제로 제기된다.

네 레벨 모두 통과해도 여전히 확인(Validation, 레슨 2)은 별개다 — 인수 테스트가 확인에 가장 가깝지만, 인수 테스트를 통과했다고 실제 만족도가 보장되진 않는다.

레벨이 올라갈수록 무엇이 '진짜'가 되는가

레벨을 가르는 실질적인 기준은 얼마나 많은 것을 진짜로 쓰느냐다. 단위 테스트는 대상 함수 하나만 진짜로 실행하고 나머지는 전부 가짜로 채운다. 시스템 테스트는 거의 모든 것을 진짜로 쓴다.

DB외부 API다른 모듈화면(UI)실행 시간
단위가짜가짜가짜없음밀리초
통합진짜 또는 테스트용대개 가짜진짜없음초
시스템진짜(테스트 환경)진짜 또는 샌드박스진짜진짜분
인수진짜(운영에 가까움)진짜진짜진짜분~시간

표의 샌드박스 는 바깥 회사가 "시험용으로 쓰라" 고 따로 열어 둔 가짜 창구다. 진짜 카드사에 진짜 결제를 보내지 않고도 결제 흐름을 끝까지 돌려 볼 수 있다.

여기서 "가짜"라고 쓴 것들이 테스트 대역(test double) 이다. 영화의 스턴트 대역처럼, 진짜 대신 자리를 채워주는 가짜 객체를 말한다. 예를 들어 배송비 계산 함수가 환율 API를 호출한다면, 단위 테스트에서는 실제로 API를 부르는 대신 "이 함수를 부르면 항상 1300을 돌려주는 가짜" 를 끼워 넣는다.

가짜로 바꾸면 세 가지가 좋아진다.

  • 빨라진다. 네트워크 왕복 200ms가 0ms가 된다.
  • 결과가 항상 같다. 환율은 매일 바뀌지만 가짜는 언제나 1300이다. 테스트가 어제는 통과하고 오늘은 실패하는 일이 사라진다.
  • 극단 상황을 만들 수 있다. 진짜 API가 타임아웃 나기를 기다릴 수는 없지만, 가짜에게는 "타임아웃 나라"고 시킬 수 있다.

대신 잃는 것도 분명하다. 가짜는 내가 믿는 대로 행동하지, 진짜가 행동하는 대로 행동하지 않는다. 진짜 API가 어느 날 응답 형식을 바꿔도 가짜는 예전 형식 그대로 답한다. 그래서 단위 테스트는 전부 초록불인데 운영에서 터지는 일이 생긴다. 이 빈틈을 메우는 것이 바로 통합 레벨의 존재 이유다.

스텁·목·페이크 같은 대역의 종류와 실제 작성법은 모듈 10(단위 테스트) 에서 다룬다. 지금은 "레벨이 낮을수록 가짜가 많고, 가짜가 많을수록 빠르지만 현실과 멀어진다"는 교환 관계만 가져가면 충분하다.

어느 레벨에서 테스트할지 고르는 기준

실무에서 실제로 부딪히는 질문은 "레벨이 몇 개냐"가 아니라 "이건 어느 레벨에서 봐야 하나" 다. 판단할 때 던지는 질문은 네 가지다.

질문아래 레벨이 유리한 쪽위 레벨이 필요한 쪽
격리할 수 있나입력을 넣으면 출력이 나오는 순수한 계산여러 컴포넌트가 함께 있어야만 성립하는 동작
경우의 수가 많은가많다 — 30가지 조합을 초 단위로 돌릴 수 있다적다 — 대표 흐름 몇 개면 된다
재현하기 쉬운가값만 바꾸면 재현된다실제 환경·타이밍이 있어야 재현된다
위험이 어디에 있나계산 규칙이 틀릴 위험연결·설정·환경이 틀릴 위험

구체적인 예로 정리하면 이렇다.

확인할 것적합한 레벨이유
배송비 경계값 29,999 / 30,000 / 30,001단위순수 계산. 세 케이스가 1초 안에 돈다
쿠폰 20종 × 회원등급 4종 조합단위80가지를 UI로 클릭하면 며칠, 함수로는 몇 초
주문 저장 후 재고가 실제로 줄었는가통합DB가 진짜여야 확인되는 동작
결제 실패 시 주문이 롤백되는가통합두 모듈 사이의 트랜잭션 경계가 대상

표의 롤백 은 "중간에 실패하면 앞서 한 것까지 전부 없던 일로 되돌린다" 는 뜻이다. 돈이 빠져나갔는데 주문은 안 만들어지는 상태를 막는 장치다. | 로그인부터 결제 완료까지 이어지는가 | 시스템 | 화면·세션·라우팅이 모두 진짜여야 성립 | | 모바일에서 결제 버튼이 가려지지 않는가 | 시스템 | 실제 렌더링 결과가 대상 | | 이 정산 리포트가 회계팀 업무에 쓸 만한가 | 인수 | 판단 주체가 사용자다 |

핵심 원칙은 하나다. 각 결함은 그것을 만들어낼 수 있는 가장 낮은 레벨에서 확인한다. 경계값 80가지 조합을 시스템 레벨에서 클릭으로 확인하는 것은 낭비이고, 반대로 화면 레이아웃 깨짐을 단위 테스트로 잡으려는 것은 불가능하다.

실패가 어느 레벨에서 잡히느냐가 디버깅을 바꾼다

레벨 선택이 중요한 진짜 이유는 비용보다 원인 좁히기의 난이도다. 테스트가 빨간불이 되었을 때, 용의자가 몇 명이냐가 레벨마다 다르다.

실패한 레벨용의자 범위원인 파악까지
단위그 함수 한 개 (수십 줄)몇 초 — 실패 메시지가 곧 원인
통합맞물린 두세 모듈과 그 사이 계약몇 분
시스템프론트·백엔드·DB·설정·네트워크 등 수십 개몇 시간, 때로는 며칠

프론트 는 사용자가 보는 화면 쪽, 백엔드 는 그 뒤에서 계산하고 저장하는 쪽을 가리킨다. 같은 버튼 하나가 안 먹어도 원인이 어느 쪽인지에 따라 고치는 사람이 달라진다. | 인수 | 위 전부 + 요구사항 해석 자체 | 회의가 필요할 수도 |

레슨 2에서 배운 오류 → 결함 → 실패의 전파를 떠올려보자. 실패를 늦게 관측할수록 결함에서 실패까지의 거리가 멀어지고, 그 사이에 낀 컴포넌트가 많을수록 역추적이 어려워진다. assertEquals(0, fee)가 깨지면 배송비 계산 로직을 보면 되지만, "결제가 안 돼요"라는 시스템 실패는 프론트의 요청 누락일 수도, 백엔드의 검증 실패일 수도, DB 커넥션 고갈일 수도, 테스트 환경의 잘못된 설정일 수도 있다.

그래서 QA 입장에서 시스템 테스트가 실패했을 때 가장 먼저 할 일은 종종 "이 실패를 더 낮은 레벨에서 재현할 수 있는가" 를 시도하는 것이다. API를 직접 호출해서(통합) 같은 오류가 나면 프론트엔드는 용의선상에서 빠진다. 이 좁히기가 결함 리포트의 품질을 결정한다.

레벨을 건너뛰면 실제로 무슨 일이 생기는가

사례 A — 통합이 비어 있던 팀

한 팀은 단위 테스트 커버리지가 85%였고 CI는 늘 초록불이었다. 주문 서비스와 회원 서비스가 REST API로 통신하는 구조였다.

회원 서비스 팀이 응답 필드 이름을 grade에서 memberGrade로 바꿨다. 자기 팀 단위 테스트는 전부 통과했다 — 새 이름으로 같이 고쳤으니까.

주문 서비스 팀의 단위 테스트도 전부 통과했다. 회원 API를 가짜로 대체해 놓았고, 그 가짜는 여전히 grade를 돌려주고 있었기 때문이다. 가짜는 진짜가 바뀐 줄 모른다.

결과적으로 두 팀 모두 초록불인 채로 배포됐고, 운영에서 모든 사용자가 등급 없음으로 처리되어 VIP 할인이 전부 사라졌다. 두 서비스를 실제로 붙여 호출하는 통합 테스트가 한 개만 있었어도 배포 전에 걸렸을 결함이다.

여기서 배울 점은 커버리지 숫자의 한계다. 단위 커버리지는 "가짜와 대화한 비율"이지 "진짜와 맞물린 비율"이 아니다. 서비스 경계를 넘는 약속(계약)은 정의상 단위 레벨에서 검증할 수 없다.

사례 B — 단위가 비어 있던 팀

반대 경우도 있다. 단위 테스트가 거의 없고 릴리즈 전에 QA가 2주간 수동 시스템 테스트를 도는 팀이다.

포인트 적립률 계산에 반올림 버그가 있었다. 결제 금액이 특정 소수점으로 떨어질 때만 1원이 어긋난다. 수동 시스템 테스트로는 이 조건을 만들려면 정확한 금액 조합을 우연히 골라야 하는데, 2주 동안 아무도 그 조합을 밟지 않았다. 단위 테스트라면 금액 200개를 넣어보는 데 1초면 충분했을 일이다.

버그는 출시 3개월 뒤 정산 불일치로 발견됐고, 소급 보정에 개발 2주와 고객 응대가 들었다. 경우의 수가 많은 계산 로직은 아래 레벨에서만 현실적으로 훑을 수 있다.

두 사례를 나란히 놓으면 결론이 하나로 모인다. 레벨은 선택지가 아니라 서로 다른 종류의 결함을 잡는 서로 다른 그물이다. 그물 하나의 코를 아무리 촘촘히 해도 다른 그물이 잡던 물고기는 잡히지 않는다.

피라미드가 뒤집히면 — 아이스크림콘 안티패턴

"아래 레벨에서 많이, 위로 갈수록 적게"를 그림으로 그리면 피라미드가 된다. 그런데 현실의 많은 조직은 정반대 모양을 하고 있다. 수동 시스템 테스트가 가장 두껍고, 통합이 얇고, 단위가 거의 없는 아이스크림콘 모양이다.

이 모양은 게을러서 생기는 게 아니라, 각 단계마다 합리적으로 보이는 선택이 쌓여서 생긴다.

왜 생기는가그 순간에는 왜 합리적으로 보이는가
일정에 쫓겨 단위 테스트를 건너뜀기능은 이미 동작한다. 테스트는 나중에 쓰면 된다
대신 QA가 손으로 확인당장은 이게 더 빠르다. 사람이 이미 있다
레거시 코드라 단위 테스트가 어려움함수가 DB·설정과 뒤엉켜 있어 떼어낼 수가 없다
눈에 보이는 것만 인정받음화면에서 확인한 것만 "테스트했다"고 인정된다
QA 조직이 개발과 분리됨QA는 코드 접근이 없으니 UI로만 확인할 수 있다

위험한 이유는 처음에는 문제가 안 보이다가 시간이 갈수록 급격히 악화된다는 점이다.

여기서 회귀(回歸) 라는 말이 처음 나온다. 고친 곳이 아니라, 고치지 않은 곳이 멀쩡한지 다시 확인하는 일을 가리킨다. 한 군데를 고쳤는데 엉뚱한 데가 망가지는 일이 흔해서, 바꿀 때마다 전체를 다시 훑어야 한다. 자세한 것은 다음 레슨에서 다룬다.

  • 회귀 비용이 기능 수에 비례해 늘어난다. 기능이 두 배가 되면 수동 회귀도 두 배가 된다. 결국 "이번 릴리즈는 전체 회귀를 못 돌립니다"가 된다.
  • 피드백이 며칠 단위가 된다. 개발자가 코드를 고친 지 사흘 뒤에 결함을 듣는다. 그때는 이미 그 코드를 잊었다.
  • QA가 회귀 노동에 갇힌다. 탐색적 테스트나 위험 분석 같은, 사람만 할 수 있는 일에 쓸 시간이 남지 않는다.
  • 릴리즈 주기를 줄일 수 없다. 배포마다 2주짜리 수동 검증이 필요하면 주 단위 배포는 물리적으로 불가능하다.

QA가 여기서 할 수 있는 가장 실질적인 기여는 결함을 레벨 관점으로 분류해서 보여주는 것이다. "지난 분기 결함 40건 중 23건은 단위 테스트로 잡을 수 있었던 계산·조건 오류였다"는 데이터는 "단위 테스트 좀 씁시다"라는 말보다 훨씬 강하다. 피라미드를 실제로 설계하고 조직에 맞게 조정하는 방법은 모듈 11(자동화 전략) 에서 다룬다.

레벨과 유형은 서로 다른 축이다

한 가지 미리 정리해둘 것이 있다. 레벨은 "어느 범위에서" 의 축이고, 다음 레슨에서 배울 테스트 유형(기능/비기능 등)은 "무엇을" 의 축이다. 둘은 곱해진다 — 단위 레벨에서 성능을 볼 수도 있고, 시스템 레벨에서 기능을 볼 수도 있다. 레벨을 정했다고 유형이 따라오지 않는다. 이 대비는 레슨 4에서 표로 자세히 다룬다.

실무에서 왜 필요한가

"이 버그는 왜 지금까지 안 잡혔나요?"에 답할 수 있다. QA가 가장 자주 받는 질문이고, 답은 대체로 "그 조건이 실행되는 레벨에서 테스트를 안 했기 때문"이다. 레벨 개념이 없으면 이 질문에 "죄송합니다, 놓쳤습니다"밖에 할 말이 없다. 있으면 "서비스 간 응답 계약이 대상이라 통합 레벨이 필요한데, 현재 통합 테스트가 없습니다"라고 재발 방지로 이어지는 답을 할 수 있다.

회귀 범위를 근거 있게 좁힐 수 있다. "이 수정의 영향 범위가 어디까지 인가"를 물었을 때, 변경이 단일 함수 내부에 갇혀 있다면 단위 테스트 통과로 충분하고, 모듈 간 인터페이스를 건드렸다면 통합부터 다시 봐야 한다. 레벨은 회귀 테스트 범위를 정하는 언어가 된다.

릴리즈 판단이 명확해진다. "테스트 다 됐나요?"라는 질문에 "네"보다 정확한 답은 "단위·통합은 CI에서 전부 통과했고, 시스템 레벨 주요 흐름 12개 중 11개 통과, 나머지 1개는 환경 이슈로 보류 중입니다"이다. 레벨별로 나눠 말할 수 있으면 위험이 어디에 남아 있는지가 드러난다.

개발자와의 협업이 구체적으로 바뀐다. "이건 조건 조합이 12가지라 UI로 다 못 돕니다. 단위 테스트로 커버해주시면 저는 대표 흐름 2개만 시스템에서 보겠습니다" — 이런 식의 분담은 레벨 개념이 공유돼 있을 때만 가능하다. QA가 무엇을 어디서 볼지 스스로 설계하는 것, 그게 테스터와 QA 엔지니어를 가르는 지점이다.

실습 과제

과제 1 — 레벨 분류하기 (10분)

"회원가입" 기능에 대해 아래 각 항목이 어느 테스트 레벨에 해당하는지 적는다.

  1. 비밀번호 유효성 검사 함수가 8자 미만을 거부하는지 확인
  2. 회원가입 API가 DB에 실제로 사용자를 저장하는지 확인
  3. 가입 완료 후 환영 이메일이 실제로 발송되고, 로그인까지 되는지 전체 흐름 확인
  4. 실제 사용자가 가입 절차를 어렵지 않게 느끼는지 베타 테스트로 확인
  5. 이미 가입된 이메일로 재가입 시도 시 회원 서비스가 409 응답을 주고, 가입 화면이 그 응답을 "이미 사용 중인 이메일입니다"로 바꿔 보여주는지 확인
해설 보기
  1. 단위 — 함수 하나가 격리된 상태로 대상이다.
  2. 통합 — API와 DB라는 두 구성요소가 맞물리는 지점이 대상이다.
  3. 시스템 — 여러 컴포넌트를 거치는 엔드투엔드 흐름이다.
  4. 인수 — 판단 주체가 실제 사용자다.
  5. 함정 문항이다. 두 개가 섞여 있다. "409를 주는가"는 통합(또는 API 레벨), "그 응답을 화면 문구로 바꾸는가"는 시스템이다. 실무의 결함 보고는 대개 이렇게 두 레벨에 걸쳐 있고, 어느 쪽이 틀렸는지 나누는 것부터가 QA의 일이다. 화면 문구가 틀렸다면 백엔드는 무죄다.

과제 2 — 무엇이 가짜인가 짚어보기 (10분)

"결제 요청 시 외부 PG사 API를 호출하고, 성공하면 주문 상태를 PAID로 바꾸고 알림 메일을 보낸다"는 기능이 있다. 단위·통합·시스템 각 레벨에서 PG사 API / DB / 메일 발송 세 가지가 각각 진짜일지 가짜일지 표로 채우고, 그렇게 정한 이유를 한 줄씩 적는다.

해설 보기
PG사 APIDB메일 발송
단위가짜가짜가짜
통합가짜(또는 샌드박스)진짜(테스트용)가짜
시스템샌드박스진짜(테스트 환경)진짜(테스트 수신함)

기준은 "이 레벨에서 검증하려는 대상이 무엇인가"다. 단위에서 확인하려는 것은 분기 로직(성공/실패에 따라 상태를 어떻게 바꾸는가)이므로 외부는 전부 가짜여도 된다. 오히려 가짜여야 "PG 실패" 같은 케이스를 마음대로 만들 수 있다.

메일이 시스템 레벨까지 가짜인 경우가 많은데, 그러면 메일이 안 가는 결함은 어디서도 안 잡힌다. 진짜 사고가 여기서 난다. 어떤 레벨에서도 진짜로 실행되지 않는 구간이 있다면, 그 구간은 사실상 테스트되지 않은 것이다 — 이 빈칸 찾기가 이 과제의 진짜 목적이다.

과제 3 — 실패 지점 좁히기 (10분)

"결제 시 할인 쿠폰이 적용 안 됨" 결함이 보고됐다. 단위·통합·시스템 중 어느 레벨의 테스트가 있었다면 이 결함을 가장 빨리, 가장 저렴하게 잡을 수 있었을지 추론해 적고, 그 이유를 한 문장으로 쓴다.

해설 보기

정답이 하나로 정해지지 않는다는 것이 이 과제의 핵심이다. 원인이 무엇이냐에 따라 답이 달라지고, 그래서 QA는 먼저 원인의 위치부터 좁혀야 한다.

  • 할인 금액 계산식이 틀렸다 → 단위. 입력·출력이 명확한 순수 계산이다.
  • 쿠폰 정보가 결제 모듈로 전달되지 않았다 → 통합. 모듈 사이 계약 문제다.
  • 계산은 맞는데 화면에 반영되지 않았다 → 시스템. 렌더링까지 봐야 한다.

좁히는 방법도 레벨 순서를 따른다. API를 직접 호출해 응답의 할인 금액이 맞다면 백엔드는 무죄고 프론트엔드로 범위가 좁혀진다. 리포트에 "API 응답에는 할인이 반영돼 있으나 화면 총액에는 반영되지 않음"이라고 쓸 수 있다면, 이미 절반은 디버깅한 것이다.

과제 4 — 사고 원인 진단하기 (10분)

아래 세 상황을 읽고, 각각 어느 레벨의 테스트가 없어서 생긴 사고인지와 추가한다면 어느 레벨에 무엇을 추가할지 적는다.

  1. 배포 후 모든 사용자의 회원 등급이 사라졌다. 원인은 회원 API의 응답 필드명 변경이었는데, 양쪽 팀 단위 테스트는 전부 통과했다.
  2. 100건 이상 주문 목록에서 페이지가 20초간 멈춘다. 개발 중에는 테스트 데이터가 5건뿐이라 아무도 못 느꼈다.
  3. 기능은 명세대로 다 동작하는데, 출시 후 "쿠폰 적용 버튼을 못 찾겠다"는 문의가 쏟아졌다.
해설 보기
  1. 통합 부재. 가짜 응답이 옛 필드명을 유지하고 있었기 때문에 단위로는 원리적으로 잡을 수 없다. 두 서비스를 실제로 붙여 호출하는 계약 검증이 필요하다.
  2. 시스템 부재(그리고 테스트 데이터 설계 부재). 성능·규모 문제는 진짜 데이터 양이 있어야 드러난다. 단위 테스트는 5건이든 5,000건이든 통과한다. 덧붙여 이건 비기능 유형의 문제이기도 하다 — 레벨과 유형이 다른 축이라는 말이 여기서 실감된다(레슨 4).
  3. 인수 부재. 명세 충족(검증)은 됐지만 쓰임 적합(확인)이 안 됐다. 레슨 1의 품질 두 축과 레슨 2의 검증·확인 구분이 그대로 적용되는 사례다. 어떤 자동화 테스트도 이건 못 잡는다.

과제 5 — 우리 팀 모양 그려보기 (선택, 15분)

지금 팀(또는 관심 있는 서비스)의 테스트가 레벨별로 몇 개씩 있는지 대략 세어보고, 피라미드인지 아이스크림콘인지 그려본다. 정확한 숫자가 아니어도 좋다 — "단위 몇백 개 / 통합 없음 / 수동 시나리오 80개"처럼 자릿수만 맞으면 충분하다.

그다음 지난 3개월간 운영에서 발견된 결함 5건을 골라, 각각 어느 레벨의 테스트가 있었다면 잡혔을지 적어본다. 이 두 장의 메모가 다음 회고에서 쓸 수 있는 가장 설득력 있는 자료가 된다.

자가 체크리스트

  • 네 가지 테스트 레벨을 확인 대상 기준으로 구분해 설명할 수 있다
  • 같은 기능의 결함이 레벨에 따라 다르게 드러나는 이유를 예시로 설명할 수 있다
  • 레벨이 낮을수록 무엇이 가짜(테스트 대역)로 대체되는지, 그 대가가 무엇인지 설명할 수 있다
  • 어떤 확인 항목을 주면 어느 레벨이 적합한지 판단 근거(격리 가능성·경우의 수·재현성·위험 위치)를 들어 고를 수 있다
  • 실패한 레벨에 따라 용의자 범위가 얼마나 달라지는지 설명할 수 있다
  • 통합 테스트가 없을 때 단위 커버리지가 높아도 놓치는 결함 유형을 예로 들 수 있다
  • "아래 레벨에서 많이, 위로 갈수록 적게" 원칙이 비용·피드백 속도와 관련 있다는 걸 설명할 수 있다
  • 아이스크림콘 안티패턴이 왜 생기고 왜 시간이 갈수록 위험해지는지 설명할 수 있다
  • 주어진 결함이 어느 레벨의 테스트 부재로 발생했는지 추론할 수 있다
  • 레벨(어느 범위)과 유형(무엇을)이 서로 다른 축이라는 것을 안다

흔한 실수

  • 통합과 시스템 레벨을 혼동한다. "두 모듈이 붙는지"는 통합, "전체 흐름이 되는지"는 시스템이다. 통합 테스트에서 이미 DB·네트워크·화면까지 다 동원해 시스템 테스트처럼 만들어버리면 느려지고 실패 원인 좁히기가 어려워진다.
  • 모든 걸 시스템/인수 레벨에서만 확인하려 한다. 느리고, 실패해도 "어디가 문제인지" 알아내는 데 시간이 오래 걸린다. 경우의 수가 많은 계산 로직을 UI 클릭으로 훑는 것은 물리적으로 불가능하다.
  • 단위 테스트 커버리지 숫자를 품질 지표로 착각한다. 커버리지 90%는 "가짜와 대화한 코드가 90%"라는 뜻이지, 진짜 환경에서 90% 동작한다는 뜻이 아니다. 서비스 경계를 넘는 결함은 정의상 단위로 못 잡는다.
  • 어느 레벨에서도 진짜로 실행되지 않는 구간을 방치한다. 메일 발송이나 외부 연동처럼 모든 레벨에서 가짜로 처리되는 부분은 사실상 미테스트 상태다. 레벨별 대역 표를 그려보면 이 빈칸이 눈에 보인다.
  • 레벨을 개발 단계(공정)와 같은 것으로 여긴다. 레벨은 범위의 개념이지 일정표가 아니다. 시스템 테스트 기간이 끝났어도 필요하면 단위 테스트를 추가한다.
  • 레벨을 조직 소유권으로 고정한다. "단위는 개발, 시스템은 QA"로 못 박으면 그 사이의 통합이 아무의 일도 아니게 된다. 실제 사고가 가장 자주 나는 곳이 바로 그 사이다.
  • 인수 테스트를 QA 혼자만의 일로 여긴다. 인수 기준은 원래 발주자·실제 사용자 관점을 반영해야 하는데, QA가 혼자 "이 정도면 됐다"고 판단하면 확인(Validation)의 의미가 옅어진다.

참고 자료

  • ISTQB Glossary — Test Levels — 단위/통합/시스템/인수 테스트의 공식 정의
  • ISTQB Foundation Level 실러버스 2장 — 테스트 레벨과 테스트 유형을 구분해 설명하는 표준 자료. 자격증을 준비한다면 이 장이 그대로 출제 범위다
  • Mike Cohn, Succeeding with Agile — 테스트 피라미드 개념이 처음 널리 알려진 출처. 자동화 전략(모듈 11)에서 다시 다룬다
  • Martin Fowler, Test Pyramid — 피라미드가 왜 그 모양이어야 하는지, 아이스크림콘이 왜 위험한지를 정리한 짧은 글
  • 다음 레슨(레슨 4, 테스트 유형)과 함께 읽으면 "어느 범위에서 × 무엇을"이라는 2차원 지도가 완성된다

낯선 말 풀이

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

QA — 품질보증
만든 것이 쓸 만한지 확인하고, 애초에 덜 망가지게 만드는 방법을 정하는 일. "테스트"는 그 일의 일부다.
DB — 데이터베이스
데이터를 넣어 두고 꺼내 쓰는 저장소. 보통 표 여러 개가 서로 연결된 형태다.
API — 응용 프로그램 인터페이스
프로그램끼리 주고받는 창구. 사람이 화면 버튼을 누르는 대신, 프로그램이 정해진 주소로 요청을 보내 답을 받는다.
UI — 사용자 인터페이스
사람이 직접 보고 누르는 부분 — 화면, 버튼, 입력창.
CI — 지속적 통합
코드를 올릴 때마다 자동으로 합쳐서 빌드하고 시험까지 돌리는 방식.
REST — 레스트
창구를 만드는 가장 흔한 방식. 주소 하나가 자원 하나를 가리키고, 동작은 정해진 몇 가지 말로 구분한다.
PG — 결제 대행
쇼핑몰과 카드사 사이에서 결제를 중개해 주는 서비스.
ISTQB — 국제 소프트웨어 테스팅 자격 위원회
테스터 자격 시험을 만들고 용어를 정리하는 국제 단체.

용어집 전체 보기