개념
테스트의 세 가지 목적
CSTS 가이드는 테스트를 "시스템이 요구사항을 만족하는지 확인하고, 표준 준수 여부를 검증하는 활동"으로 놓고, 그 목적을 세 가지로 나눈다.
| 목적 | 무엇을 하는가 | 결과가 쓰이는 곳 |
|---|---|---|
| 결함 검출과 제품 품질 개선 | 결함을 찾아 제거되게 한다 | 개발자의 수정 |
| 품질 평가와 의사 결정 지원 | 성능·신뢰성·보안성 등 품질 특성의 충족 수준을 평가한다 | 출시 여부 같은 제품 의사 결정 |
| 개발 프로세스 개선 지원 | 결함이 어느 단계에서 생겼고 왜 못 잡았는지 분석한다 | 다음 프로젝트의 프로세스 |
세 번째 목적이 자주 출제된다. 예를 들어 검출된 결함 가운데 요구사항 관련 결함이 유난히 많다면, 그 사실은 요구분석 단계의 프로세스와 그 단계의 결함 검출 방법 을 고쳐야 한다는 신호다. 테스트 결과가 제품만이 아니라 일하는 방식 을 고치는 데 쓰인다는 점이 핵심이다.
오류 · 결함 · 장애 — 원인에서 현상까지
이 세 단어는 인과의 사슬로 외우면 헷갈리지 않는다.
사람이 실수한다 → 산출물에 문제가 남는다 → 실행했을 때 기대와 다르게 동작한다
오류 (Error) 결함 (Defect) 장애 (Failure)- 오류(Error) — 결함을 만들어 낸 사람의 행위. 요구사항을 잘못 이해한 것, 오타, 명령어를 잘못 알고 쓴 것.
- 결함(Defect) — 소프트웨어 안에 있는, 장애를 일으킬 수 있는 문제. 부정확한 구현이거나 필요한 기능이 빠진 것.
- 장애(Failure) — 프로그램의 실행 결과가 요구사항에 적힌 결과와 관찰 가능하게 다른 것.
가장 자주 나오는 함정 문장은 이것이다. "결함이 있으면 반드시 장애가 발생한다." 틀렸다. 결함 때문에 장애가 생기지만, 결함이 있다고 해서 반드시 장애가 생기지는 않는다. 결함이 있는 코드가 실행되지 않거나, 실행되더라도 그 결함을 드러내는 입력이 들어오지 않으면 장애는 관찰되지 않는다.
간단한 예로 확인해 보자. 차량용 AV 시스템에 "USB를 꽂으면 그 안의 오디오·비디오가 재생되어야 한다"는 요구사항이 있다. USB를 꽂았는데 인식이 안 되거나, 인식은 되는데 재생이 안 된다면 그것이 장애 다. 그 원인이 USB 드라이버의 특정 파일 시스템 처리 누락이라면 그것이 결함 이고, 개발자가 그 파일 시스템을 지원 대상에서 빠뜨린 판단이 오류 다.
결함 유형 세 가지 — 누락, 부정확한 구현, 비관련
요구 명세와 구현을 두 개의 원으로 그리면 결함 유형이 한눈에 보인다.
| 유형 | 영문 | 위치 | 예 |
|---|---|---|---|
| 누락 | Omission | 명세에는 있는데 구현에 없다 | 명세는 특정 입력에 A를 출력하라는데 그 처리가 없다 |
| 부정확한 구현 | Incorrect | 명세와 구현이 겹치지만 어긋나 있다 | 명세는 A를 출력하라는데 B가 나온다 |
| 비관련 | Extraneous | 구현에는 있는데 명세와 관계가 없다 | 요구와 무관한 메모리 할당, 쓰이지 않는 파일 열기 |
두 가지를 기억해 두면 응용 문제에서 흔들리지 않는다.
첫째, 누락과 부정확한 구현은 기능만이 아니라 성능·보안·안전·신뢰도 같은 품질 요소에도 해당 한다. "응답 시간 2초 이내" 요구가 있는데 측정 장치 자체가 구현되지 않았다면 누락, 5초가 걸린다면 부정확한 구현이다.
둘째, 비관련 결함은 당장 장애를 일으키지 않을 수도 있다. 그런데도 결함으로 분류하는 이유는, 의미 없는 코드가 불필요한 분석·테스트·관리 노력을 만들고 결국 다른 결함의 원인이 되기 때문이다.
이차방정식의 해를 구하는 함수를 예로 들면 세 유형이 한 화면에 다 나온다. 판별식을
b*b - 4*a*c 가 아니라 b*b - 4*a*b 로 쓴 것은 부정확한 구현이다. a 가 0일 때
분모가 0이 되는 경우를 막지 않은 것도 부정확한 구현이다. 판별식이 음수일 때 허근을
구하는 분기가 아예 없다면 누락이다. 해를 구하는 일과 무관하게 큰 배열을 할당하고
파일을 여는 줄이 있다면 비관련이다.
결함은 코드에만 있지 않다 — 단계별 발생과 해결 비용
결함은 소스 코드를 포함해, 최종적으로 장애를 일으킬 수 있는 모든 개발 산출물 에 있을 수 있다. 소스 코드에서 발견된 결함이 사실은 설계 명세서의 잘못된 알고리즘에서 왔다면 그것은 설계 결함이다.
가이드가 인용하는 자료에 따르면 결함 발생 비율은 대략 이렇다.
| 단계 | 비율 |
|---|---|
| 코딩 | 35% |
| 설계 | 25% |
| 요구분석 | 20% |
| 문서화 | 12% |
| 결함 해결 오류(고치다가 새로 생긴 결함) | 8% |
코딩 단계가 가장 많지만, 요구분석과 설계를 합치면 45% 로 코딩보다 많다는 점이 중요하다. 코드만 테스트해서는 결함의 절반 가까이를 늦게 잡게 된다.
늦게 잡을수록 비용이 커진다. 요구분석 단계에서 고치는 비용을 0.1~0.2로 놓으면, 설계 0.5, 코딩 1, 단위 테스트 2, 인수 테스트 5, 유지보수 단계 20으로 커진다. 요구분석 단계 대비 최대 100배 이상 차이가 난다. 그래서 각 단계의 산출물을 그 단계에서 테스트(리뷰 등)해 결함을 빨리 잡아야 한다는 결론이 나오고, 이것이 뒤에 나올 "초기에 테스트하라"는 원칙과 V 모델의 근거가 된다.
테스팅 · 디버깅 · 재테스팅
| 활동 | 목적 | 하는 사람(일반적) | 결과물 |
|---|---|---|---|
| 테스팅 | 실제 동작과 요구사항의 차이를 확인 한다 | 테스터 | 결함을 드러낸 테스트 케이스와 환경 |
| 디버깅 | 결함의 위치를 찾고 제거 한다 | 개발자 | 수정된 코드 |
| 재테스팅 | 결함이 실제로 제거되었는지 확인 한다 | 테스터 | 처음 결함을 찾은 케이스의 재실행 결과 |
테스팅은 장애를 관찰해 결함이 있다고 간접적으로 판단한다. 어느 모듈의 어느 줄이 문제인지, 어떻게 고쳐야 하는지에는 관여하지 않는다. 그 일은 디버깅이다. 그리고 재테스팅은 처음에 결함을 검출한 바로 그 테스트 케이스 로 다시 수행한다는 점이 정의의 핵심이다. 수정이 다른 곳을 망가뜨리지 않았는지 보는 것은 재테스팅이 아니라 리그레션 테스트다(레슨 5에서 다룬다).
완벽한 테스트는 불가능하다
이차방정식 프로그램의 a, b, c를 2바이트 정수로만 제한해도 입력 조합은 2의 16제곱을 세 번 곱한 수만큼 나온다. 워드프로세서의 글꼴 대화 상자만 해도 글꼴 30개 × 스타일 5개 × 크기 21개로 3,150가지이고, 색·밑줄·효과까지 더하면 셀 수 없이 늘어난다.
다익스트라의 말이 이 한계를 요약한다. "프로그램 테스트는 결함이 있음을 보일 수는 있지만, 없음을 보일 수는 없다." 가이드는 이를 낚시에 비유한다. 미끼(테스트 데이터)를 다 쓸 때까지 물고기(결함)가 안 잡혔다고 저수지에 물고기가 없다고 말할 수는 없다.
그래서 결론은 "더 많이"가 아니라 "체계적으로" 다. 동등 분할·경계값 분석·조합 테스트처럼 케이스 수를 줄이면서 결함을 놓치지 않는 설계 기법, 그리고 위험 분석으로 범위를 정하는 위험 기반 테스트가 이 한계에 대한 대응이다.
테스트 개념의 진화 — 겔퍼린과 헤첼의 다섯 레벨
| 레벨 | 이름 | 시기 | 테스트를 무엇으로 보았나 |
|---|---|---|---|
| 1 | Debugging-oriented | ~1956 | 테스트와 디버깅의 구분이 없다 |
| 2 | Demonstration-oriented | 1957~1978 | 프로그램이 올바르게 동작함을 보이는 것 |
| 3 | Destruction-oriented | 1979~1982 | 프로그램에 결함이 있음을 보이는 것 |
| 4 | Evaluation-oriented | 1983~1987 | 개발 전 단계 에서 리뷰 등으로 평가하는 것 |
| 5 | Prevention-oriented | 1988~ | 결함이 생기지 않도록 예방 하는 것 (TDD가 예) |
레벨 2의 기간은 1957~1978 이다. 오래된 판에는 "1957~1878"이라는 오타가 있었고 정오표로 바로잡혔다. 시험에서는 기간 숫자보다 각 레벨이 테스트의 목적을 어떻게 보았는가 를 묻는 경우가 많다. "결함을 찾는 케이스가 못 찾는 케이스보다 가치 있다"는 인식이 생긴 것은 레벨 3, "코딩이 끝나기 전부터 리뷰로 평가한다"는 레벨 4, "케이스를 먼저 설계해 결함을 미리 막는다"는 레벨 5다.
테스트 원칙 — 마이어스가 말한 것
가이드는 마이어스의 『The Art of Software Testing』에서 몇 가지 원칙을 골라 소개한다.
- 테스트는 개발한 프로그래머나 팀과 무관한 그룹이 해야 한다. 자기 코드에는 방어적이 되고, 요구사항을 잘못 이해했다면 테스트도 같은 오해 위에서 하게 된다.
- 결함이 발견되지 않으리라는 가정으로 계획을 세우지 마라. 테스트는 올바름을 보이는 일이 아니라 결함을 찾으려는 의도로 실행하는 일이다(레벨 3의 관점).
- 타당하지 않고 예상하지 못한 입력도 테스트하라. 정수를 받는 곳에 문자열을 넣는 것처럼, 예상 밖 사용에서 결함이 많이 나온다.
- 결함이 남아 있을 확률은 그 부분에서 이미 발견된 결함 수에 비례한다. 파레토 원칙 — 결함의 80%는 20%의 모듈에서 나온다. 결함이 많이 나온 곳에 노력을 집중한다.
- 테스트 케이스를 체계적으로 관리하라. 수정 후 다시 테스트할 때 재사용해야 하기 때문이다.
- 각 테스트 결과를 철저히 점검하라. 앞서 실행한 케이스에서 이미 나타난 결함을 지나치는 일이 흔하다.
강의 자료에서는 ISTQB식 7원칙(결함의 존재를 보여 준다, 완벽한 테스트는 불가능하다, 조기 테스트, 결함 집중(파레토), 살충제 패러독스, 상황 의존성, 오류 부재의 궤변)으로 정리하기도 한다. 두 목록은 겹치는 부분이 많다. 살충제 패러독스 는 같은 케이스를 반복하면 더 이상 새 결함을 찾지 못하니 케이스를 주기적으로 보강해야 한다는 뜻이고, 오류 부재의 궤변 은 결함을 다 잡아도 사용자가 원하지 않는 시스템이면 소용없다는 뜻이다. 시험 보기에 둘 중 어느 표현이 나와도 뜻을 알아볼 수 있게 해 둔다.
테스트 · V&V · 품질 보증 — 무엇이 무엇을 포함하는가
세 개념은 포함 관계다. 품질 보증 ⊃ V&V ⊃ 테스트.
- 테스트 는 V&V를 수행하는 여러 방법 가운데 하나다.
- V&V(Verification and Validation) 는 검증과 확인이다. 29119-1 부록의 분류로는 V&V가 정형 방법(모델 체킹, 정확성 증명), 테스팅(동적·정적), V&V 분석(시뮬레이션, 평가)으로 나뉜다. 테스트 말고도 V&V를 하는 방법이 있다는 뜻이다.
- 품질 보증(QA) 은 제품의 품질뿐 아니라 프로세스의 품질 까지 포함한다. ISO/IEC 12207은 품질 보증을 "제품과 프로세스가 적합하다는 확신을 주기 위한 활동"으로 본다. 그래서 V&V보다 넓다.
검증과 확인 의 구분은 거의 매 회 출제된다.
| 검증 (Verification) | 확인 (Validation) | |
|---|---|---|
| 질문 | 시스템을 올바르게 만들고 있는가? | 올바른 시스템을 만들고 있는가? |
| 기준 | 명세(앞 단계의 산출물) | 사용자의 요구와 기대 |
| 초점 | 개발 과정 활동의 적합성 | 결과물의 적합성 |
| 예 | 요구사항 명세가 설계에 반영되었는지 추적성 확인 | 동작하는 소프트웨어가 사용자 요구를 충족하는지 확인 |
| 대표 테스트 레벨 | 단위·통합·시스템 테스트 | 인수 테스트 |
시스템 명세에 사용자의 운영 환경이 반영되어 시스템 테스트에 들어간다면 시스템 테스트도 확인의 성격을 띨 수 있다는 단서도 기억해 둔다.
실무에서 왜 필요한가
결함 리포트 제목에 "로그인 결함"이라고 쓰는 것과 "잘못된 비밀번호 5회 입력 후에도 계정이 잠기지 않는 장애"라고 쓰는 것은 다르다. 앞쪽은 원인을 단정했고, 뒤쪽은 관찰한 사실을 적었다. 테스터는 장애를 관찰하는 사람이고, 결함의 위치는 디버깅으로 밝혀진다. 이 구분을 지키면 "제 코드에는 문제없는데요"라는 방어적인 답을 덜 듣는다.
결함 유형 세 가지는 리뷰 체크리스트로 바로 쓸 수 있다. 요구사항 한 줄마다 "이게 구현에 있나(누락)", "있다면 맞게 됐나(부정확)", 그리고 구현 쪽에서 "이 기능은 어느 요구에서 왔나(비관련)"를 묻는다. 특히 비관련은 기획에 없는 숨은 기능이나 디버그 코드가 운영에 남은 경우를 잡아낸다. 보안 사고의 상당수가 이런 코드에서 나온다.
단계별 결함 비용은 일정 협상의 근거가 된다. "요구사항 리뷰에 하루를 쓰자"는 제안은 감으로 하면 거절당하지만, 늦게 잡은 결함 하나가 초기 대비 수십 배 비용이라는 자료와 함께 내면 받아들여질 가능성이 커진다.
채용시장에서의 위치
신입 QA 면접의 기술 질문 상당수가 이 레슨에서 나온다. "버그와 결함의 차이", "테스트와 디버깅의 차이", "검증과 확인의 차이", "QA와 테스트의 차이"는 거의 고정 질문이다. 이때 정의만 외워 말하면 평범한 답이 되고, 예 하나를 붙이면 눈에 띄는 답이 된다. 예를 들어 QA와 테스트의 차이를 물으면 "테스트는 제품의 결함을 찾는 활동이고, QA는 그 결함이 애초에 덜 생기도록 프로세스까지 관리하는 활동입니다. 예를 들어 요구사항 결함이 계속 많이 나오면 테스트는 그걸 계속 잡지만, QA는 요구사항 리뷰 절차를 추가합니다"처럼 답한다.