본문으로 건너뛰기
입문18

완전한 테스트는 불가능하다 — 한계와 기대치 조정

왜 모든 입력 조합을 테스트할 수 없는지 숫자로 확인하고, 버그 없음을 보장해달라는 요청에 QA가 어떻게 답해야 하는지 연습한다.

  • #테스트한계
  • #소진적테스트
  • #리스크기반
  • #QA기초

개념

조합이 폭발한다

간단해 보이는 폼도 모든 입력 조합을 테스트하면 숫자가 순식간에 감당 못 할 크기가 된다.

회원가입 폼에 필드 5개(이메일, 비밀번호, 닉네임, 생년월일, 약관 동의)가 있고, 각 필드에 "유효값 / 경계값 / 비유효값" 정도로만 값을 잡아도 필드당 최소 3가지 경우가 나온다.

5개 필드 × 3가지 경우 = 3⁵ = 243가지 조합. 여기에 필드 간 상호작용(비밀번호와 비밀번호 확인이 다른 경우 등)까지 더하면 순식간에 수천 가지로 늘어난다. 이건 필드 5개짜리 폼 얘기다 — 실제 서비스는 화면 하나에도 필드가 훨씬 많고, 화면 간 조합까지 따지면 모든 경우를 다 테스트하는 건 수학적으로 불가능하다.

그래서 에츠허르 데이크스트라(Edsger Dijkstra)의 유명한 말이 있다.

"테스트는 결함이 있다는 것을 보여줄 수 있을 뿐, 결함이 없다는 것을 보여주지는 못한다." (Testing shows the presence of defects, not their absence)

테스트를 아무리 많이 통과해도 "버그가 없다"를 증명하는 게 아니라 "우리가 시도한 조건에서는 버그가 안 보였다"는 것만 말해준다.

그래서 테스트는 "표본 추출"이다

모든 조합을 볼 수 없으니, QA는 어디를 볼지 전략적으로 고른다. 이게 모듈 3(테스트 설계 기법)에서 배울 동등분할·경계값 같은 기법의 존재 이유이고, 모듈 4(리스크 기반 테스트)에서 배울 "어디에 시간을 더 쓸지"를 결정하는 이유다. 테스트는 "다 보는 일"이 아니라 "제한된 시간 안에 가장 위험한 곳을 가장 잘 보는 일"이다.

같은 테스트를 반복하면 효과가 줄어든다

같은 테스트 스위트를 계속 똑같이 돌리면, 그 스위트가 잡을 수 있는 결함은 이미 다 잡혀서 더 이상 새로운 결함을 못 찾는다 — 이걸 **살충제 패러독스(Pesticide Paradox)**라고 부른다. 같은 살충제를 계속 쓰면 벌레가 내성이 생기는 것에 빗댄 표현이다. 그래서 테스트 스위트도 주기적으로 새로 만들거나 바꿔야 하고, 스크립트로 정해지지 않은 영역을 보는 탐색적 테스팅(모듈 5)이 계속 필요하다.

"완전한 테스트 불가능"이 뜻하지 않는 것

이 원칙은 "그러니 대충 해도 된다"는 뜻이 아니다. 오히려 "어디까지 테스트하면 충분한가"를 의도적으로, 근거를 갖고 정해야 한다는 뜻이다. 무엇이 "충분"인지는 맥락에 따라 다르다 — 개인 블로그와 의료기기 소프트웨어는 요구되는 테스트 수준이 전혀 다르다. 이 "얼마나 테스트할 것인가"를 결정하는 방법은 모듈 4(리스크 기반 테스트)에서, 언제 테스트를 멈출지 판단하는 기준(테스트 종료 조건)도 같은 모듈에서 다룬다.

실무에서 왜 필요한가

기획자나 경영진이 "이번 릴리즈는 버그 없이 나가는 거죠?"라고 물어보는 상황은 실무에서 드물지 않다. 이걸 "네" 또는 "아니오"로 답하면 둘 다 문제가 된다 — "네"는 지킬 수 없는 약속이고, "아니오"만 답하면 QA가 일을 안 하는 것처럼 들린다. 실무에서 필요한 답은 "어떤 리스크를 얼마나 줄였는지"를 근거로 설명하는 것이다. 예: "핵심 결제 흐름은 경계값까지 포함해 촘촘히 봤고, 발견된 결함은 모두 수정·재확인했습니다. 다만 모든 입력 조합을 볼 수는 없어서, 리스크가 낮다고 판단한 영역(예: 잘 안 쓰는 설정 화면)은 상대적으로 얕게 봤습니다." 이런 식으로 "무엇을 왜 안 봤는지"까지 설명할 수 있는 것이 신뢰를 만든다.

실습 과제

과제 1 — 조합 폭발 계산하기 (10분)

로그인 폼에 필드가 3개(아이디, 비밀번호, "로그인 상태 유지" 체크박스) 있고, 아이디와 비밀번호 각각 4가지 경우(정상/빈값/형식오류/존재하지않음), 체크박스는 2가지 경우가 있다고 하자. 전체 조합 수를 계산해본다. 그다음, 실제로 이 모든 조합을 다 테스트할 필요가 있을지, 어떤 조합을 줄일 수 있을지 한 문단으로 적는다.

과제 2 — "버그 없음"을 보장해달라는 요청에 답하기 (10분)

"이번 릴리즈, 버그 없이 나가는 거 맞죠?"라는 질문에 답하는 2~3문장짜리 대답을 직접 써본다. "네/아니오"로 시작하지 않고, 무엇을 테스트했고 무엇이 리스크로 남아있는지를 포함해서 쓴다.

자가 체크리스트

  • 간단한 폼에서도 입력 조합이 기하급수적으로 늘어나는 이유를 계산으로 보여줄 수 있다
  • "테스트는 결함의 존재를 보여줄 뿐 부재를 증명하지 못한다"는 말의 의미를 설명할 수 있다
  • 살충제 패러독스가 왜 테스트 스위트를 주기적으로 바꿔야 하는 근거가 되는지 설명할 수 있다
  • "버그 없음을 보장해달라"는 요청에 근거 있는 답변을 만들 수 있다
  • "완전한 테스트 불가능"이 "대충 해도 된다"는 뜻이 아님을 설명할 수 있다

흔한 실수

  • "테스트를 통과했다 = 버그가 없다"고 이해관계자에게 전달한다. 정확히는 "우리가 시도한 조건에서는 안 보였다"이다. 이 차이를 흐리면 나중에 신뢰 문제가 된다.
  • 모든 조합을 다 보려고 시도하다가 정작 위험한 곳을 놓친다. 시간은 유한하다. 낮은 리스크 영역에 시간을 쓰느라 높은 리스크 영역이 얕아지면 우선순위가 잘못된 것이다.
  • 같은 회귀 스위트를 몇 년째 그대로 돌리면서 "테스트하고 있다"고 안심한다. 살충제 패러독스대로, 새로운 결함은 그 스위트 바깥에 있을 가능성이 높다.

참고 자료