제 1장 테스팅의 기초
제 1장 테스팅의 기초
1.1 테스팅이란 무엇인가?
소프트웨어 테스팅이란 다양한 활동을 포함하는 프로세스이며 테스트 실행은 그 많은 활동 중 하나일 뿐이다.
테스트 프로세스는 테스트 계획, 분석, 설계, 테스트 구현, 테스트 진행 상황 및 결과 보고, 테스트 대상 품질 평가 등 많은 활동을 포함한다.
동적 테스팅이란 테스트 대상 컴포넌트나 시스템을 실행한다. 반면 실행하지 않은 것은 정적 테스팅이라고 부른다.
1.1.1 테스팅의 일반적인 목적
- 요구사항, 스토리, 설계, 소스 코드 등 작업 산출물 평가에 의한 결함 예방
- 명시된 모든 요구사항이 충족됐는지 검증
- 테스트 대상의 완성 여부 확인과 기대치 대로 동작하는 지 확인
- 테스트 대상 품질 수준에 대한 자신감 획득
- 부적절한 소프트웨어 품질 리스크 레벨 감소로 장애와 결함 발견
- 테스트 대상 품질 수준 결정하는 데 필요한 충분한 정보 제공
- 요구사항이나 표준의 준수 여부 확인
위와 같은 테스팅의 목적은 테스트 컴포넌트나 시스템의 상황에 따라 달라질 수 있다.
1.1.2 테스팅과 디버깅
테스팅과 디버깅은 다르다. 테스트를 실행하면 소프트웨어 결함으로 인한 장애를 찾을 수 있으며, 디버깅은 그런 장애의 원인을 찾고 분석해서 수정하는 개발 활동이다. 테스터가 초기 테스트와 마지막 확인 테스트를 담당하고 개발자는 디버깅 관련 컴포넌트를 수행한다. 반면, 애자일 개발 관련해서는 테스터가 디버깅과 컴포넌트 테스팅에 관여하기도 한다.
1.2 테스팅이 왜 필요한가?
결함을 발견하고 결함을 수정하는 것은 시스템 품질에 기여하는 것이다. 소프트웨어 테스팅이 계약/법적 요구사항이나 특정 산업 표준을 만족시키기 위해 필요할 수도 있다.
1.2.1 성공을 위한 테스팅 기여
컴퓨터 역사에서 소프트웨어와 시스템이 배포된 후 결함 장애나 요구를 충족시키지 못하는 상황은 늘 있었다. 적절한 테스트 기법을 전문성을 가지고 적절한 레벨과 개발 수명 주기 단계에 적용하면, 소프트웨어와 시스템이 그런 문제를 안고 배포되는 경우를 줄일 수 있다.
1.2.2 품질 보증과 테스팅
품질 보증(QA)와 테스팅은 다른 개념이다. 둘 다 좀 더 포괄적인 개념인 품질 관리에 속한다. 품질 관리는 품질 측면에서 조직이 나아가야 하는 방향을 제시하고 제어하는 모든 활동을 포함. 일반적으로 품질 보증은 적절한 품질 수준을 달성했는지 확신을 얻기 위해 적절한 프로세스를 준수하도록 하는 것에 초점. 프로세스 따를 경우 작업 산출물의 품질은 더 높으며, 결함 원인 찾아서 제거하기 위한 근본 원인 분석과 회고 회의 결과를 적절하게 적용해 프로세스를 개선해야 한다.
품질 제어에도 다양한 활동이 있으며 테스트 활동이 여기에 포함된다. 테스트 활동은 전반적인 소프트웨어 개발 및 유지보수 프로세스의 일부이다. 테스팅은 품질을 높이는 데 다양한 방법으로 기여한다.
1.2.3 오류, 결함, 장애
사람은 산출물을 작성하며 결함을 발생시키는 오류를 범하고, 특정 결함의 오류는 다른 산출물의 원인이 된다. 요구사항을 도출하며 범해진 오류는 요구사항 결함이 되며, 이런 결함은 프로그램 작성 시 오류를 일으켜 결국 코드 결함이 된다. 하지만 반드시 그런 것은 아니다. 결함 중 일부는 발생 가능성이 없거나 매우 낮아 조건을 충족해야 장애를 일으킨다.
- 대표적인 오류 발생 원인 : 시간 압박, 사람의 실수, 경험 적은 프로젝트 참여자, 요구사항과 설계 등 프로젝트 참여자 간의 의사소통 문제, 사용 기술의 복잡도, 인터페이스 이해 부족, 새로운 기술 등
환경 조건으로도 발생할 수 있다. 전자기장 등은 펌웨어 결함의 원인이 되거나 하드웨어 상태를 변화시킴으로써 소프트웨어 실행에 영향을 줄 수 있다.
테스트 결과가 기대한 것과 다르다 해서 무조건 장애가 있다고 볼 수 없다. 다양한 이유로 거짓양성이 발생할 수 있다. 거짓 음성의 원인이 되는 반대의 경우도 있다. 거짓 음성은 테스트가 발견했어야 할 결함을 발견하지 못하는 경우이며, 거짓양성은 결함으로 보고됐지만 실제 결함이 아닌 경우를 말한다.
1.2.4 결함, 근본 원인, 결과
결함의 근본 원인은 해당 결함을 만들어낸 최초의 행동이나 조건이다. [ 결과, 장애, 결함, 최초 결함 ]
1.3 테스팅의 7가지 원리
(1) 테스팅은 결함이 존재함을 밝히는 활동이지, 결함이 없음을 밝히는 활동이 아니다. : 테스팅은 결함이 존재한다는 것을 보여줄 수 있지만, 결함이 없다는 것을 증명할 수 없다. 결함이 전혀 발견되지 않았다 하더라도 해당 소프트웨어가 완벽하다는 뜻은 아니다.
(2) 완벽한 테스팅은 불가능하다. : 모든 입출력을 테스팅 한다는 것은 불가능하다. 완벽하게 테스티하고자 하기보다는 리스크 분석과 우선순위를 토대로한 테스트에 노력을 집중하는 것이 좋다.
(3) 조기 테스팅으로 시간과 비용을 절약할 수 있다. : 초기에 결함을 찾기 위해서는 정적 및 동적 테스트 활동 모두 소프트웨어 개발 수명주기 중 가능한 이른 시점에 시작해야 한다. 초기부터 시작하는 테스팅을 시프트 레프트라고 부른다.
(4) 결함은 집중된다. : 출시 전 테스팅에서 발견하는 대부분 결함은 소수의 모듈에 집중되어 발생된다. 예상 결함 집중 영역과 테스트와 운영 중 실제로 관측한 결함 집중 영역은 리스크 분석의 주요 입력값으로 사용된다.
(5) 살충제 패러독스에 유의 : 같은 테스트 계속 반복 실행시 해당 테스트로는 결함을 더 이상 발견할 수 없음. 새로운 결함을 발견하기 위해선 새로운 테스트 작성 필요. 반면 자동 리그레션 테스팅의 경우 리그레션 결함이 적다는 의미이기도.
(6) 테스팅은 정황(context)에 의존적이다. : 정황에 따라 다르게 진행된다. 산업에 따라 다르게 테스트 진행되면 애자일의 경우 순차적 소프트웨어 개발 수명주기와 다르게 진행된다.
(7) 오류 부재는 궤변이다 : 단순히 많은 결함을 발견하고 고쳤다 해서 시스템의 성공이 보장된다고 생각하는 건 궤변이다.
1.4 테스트 프로세스
모두가 사용하는 일반적 테스트 프로시저는 없지만, 설정한 목표 달성 가능성을 높여주는 공통 테스트 활동 세트는 존재한다. 이런 활동 세트를 테스트 프로세스라 한다.
1.4.1 정황에 따른 테스트 프로세스
사용중인 소프트웨어 개발 수명 주기 모델과 방법론, 테스트 레벨과 유형, 제품, 리스크, 비즈니스 도메인, 예산과 자원, 일정, 복잡도, 계약 및 요구사항, 운영정책, 프랙티스, 표준 등
테스트 레벨과 유형에 상관없이, 베이시스에 대한 측정 가능한 커버리지 조건이 서절되어 있으면 매우 유용한다. 커버리지 조건은 주요 성능 지표 (kpi)로 사용하기 용이하다. 각각의 요구사항과 테스트 대상 기기를 하나의 테스트 베이시스 요소로 보고, 커버리지 조건은 하나의 테스트 케이스를 다루어야 한다는 것이다.
1.4.2 테스트 활동과 작업
테스트 계획 > 테스트 모니터링과 제어 > 테스트 분석 > 테스트 설계 > 테스트 구현 > 테스트 실행 > 테스트 완료
각 주요 활동은 구성 활동으로 이루어지며, 각 구성 활동은 다시 다수의 개별 작업으로 나눠지며 프로젝트 또는 릴리즈마다 달라질 수 있다. 이런 주요 활동이 순차적으로 이루어지는 것처럼 보이나, 반복적으로 구현되는 경우가 많다. 애자일의 경우 설계 빌드 테스트 이 3항목을 작은 주기로 반복해서 배치한다. 순차 소프트웨어 개발에서도 개별 활동의 논리적 순서는 중첩, 조합, 동시 실행 되거나 누락된다.
(1) 테스트 계획
테스팅의 목적과 정황으로 인한 제약 사항을 고려해 테스트 목적을 달성하기 위해 필요한 접근법을 정의하는 활동을 포함한다. 적합한 테스트 기법, 작업 명시, 테스트 일정 수립이 포함된다. 이는 모니터링과 제어 활동에서 나온 피드백으로 수정할 수 있다.
(2) 테스트 모니터링과 제어
테스트 계획에 정의된 메트릭을 활용해 실제 진행 상황을 계획한 진척상황과 지속적으로 비교하는 활동. 시간이 지나면서 업데이트가 필요한 테스트 계획의 목적 달성을 위해 활동 수행. 종료 조건 평가도 테스트 모니터링과 제어에 필요한 활동이며, 일부 모델에서는 종료 조건은 완료 정의로 칭하기도 한다.
- 테스트 실행의 종료 조건 평가 : 명시된 커버리지 조건 대비 테스트 결과와 로그 확인, 이를 기반으로 컴포넌트나 시스템의 품질 수준 평가, 추가 테스트 필요 여부 결정.
계획 대비 테스트 진행 상황은 테스트 진행 상황 보고서의 형태로 전달되며, 편차와 테스트 그만두기로 했으면 뒷받침할 정보도 필요.
(3) 테스트 분석
테스트 가능 기능과 테스트 컨디션 식별하기 위한 베이시스 분석. 테스트 분석은 커버리지 조건 중 '무엇을 테스트 할지' 결정하는 것.
- 고려 중인 테스트 레벨에 적합한 테스트 베이시스 평가
요구사항
(비즈니스, 기능, 시스템, 스토리, 유스케이스 등)
설계와 구현 정보
(아키텍처 다이어그램 문서, 콜흐름도, 모델링, 인터페이스 등)
코드, 데이터베이스 데이터, 쿼리, 인터페이스, 리스크 분석 보고서 등 - 테스트 베이시스와 테스트 항목을 평가해 다양한 형태 결함 식별 : 모호함, 누락, 불일치, 부정확, 모순, 불필요한 구문 등
- 테스트할 기능과 기능 세트 식별
- 테스트 베이시스 평가 및 각 요소의 수준을 고려해 테스트 컨디션과 우선순위 선정
- 테스트 베이시스의 개별 요소와 연관된 테스트 컨디션 간 양방향 추적성 포착
테스트 분석에 블랙박스, 화이트박스, 경험 기반 기법 적용 시 주요 테스트 컨디션 누락을 방지하고 더욱 정밀한 테스트 가능하다. 테스트 분석 결과로 테스트 차터의 테스트 목적으로 사용할 컨디션이 생성될 수도 있다. 테스트 차터는 일부 경험 기반 테스팅 유형에서 일반적으로 사용하는 작업 산출물이다. 테스트 목적과 베이시스 간 추적성을 확인 가능한 경우, 이런 경험 기반 테스팅으로 달성하는 커버리지를 측정할 수 있다.
테스트 분석 중 결함 식별은 큰 잠재적 이점이다. 이런 테스트 분석 활동은 요구사항이 일관성 있게 제대로 완성되었는 지 검증하고, 요구사항이 제대로 반영되었는 지 확인한다. 예를 들어 코딩 전 사용자 스토리와 인수조건으로부터 테스트 컨디션과 케이스를 도출하는 행위 주도 개발과 인수 테스트 주도 개발이 있다.
(4) 테스트 설계
테스트 컨디션 기반 상위 수준 테스트 케이스, 세트, 테스트웨어를 생성한다. 분석은 무엇을 테스트?라는 질문에 답변했다면 설계는 어떻게 테스트?를 다룬다. 테스트 설계 중 컨디션을 케이스와 세트로 전환할 때 테스트 기법 사용한다.
- 테스트 케이스와 테스트 세트 설계 및 우선순위 설정
- 테스트 컨디션과 케이스에 필요한 테스트 데이터 식별
- 테스트 환경 설계 및 필요한 인프라 및 도구 식별
- 테스트 베이시스, 컨디션, 케이스 간 양방향 추적성 설정
(5) 테스트 구현
테스트 실행에 필요한 테스트웨어를 생성하고 완성하며, 테스트 케이스를 배치 해 테스트 프로시저를 만드는 것. 테스트 구현은 테스트 실행하기 위해 필요한 모든 것이 있는가?에 답변
- 테스트 프로시저의 개발과 우선 순위 선정, 자동 테스트 스크립트 생성
- 테스트 프로시저와 자동 테스트 스크립트로 부터 테스트 스위트 생성
- 효과적 테스트를 위해 테스트 스위트를 일정 내에 배치
- 테스트 환경 구축, 테스트 하네스, 서비스 가상 현실화, 시뮬레이터, 인프라 등 필요한 모든 사항 구현 확인
- 테스트 데이터 준비, 환경에 제대로 입력했는 지 확인
- 베이시스, 컨디션, 케이스, 프로시저, 스위트 서로 간 양방향 추적성 검증과 업데이트
테스트 설계와 구현은 합쳐지는 경우가 많다.
탐색적 테스팅과 경험 기반 테스팅 유형에서 테스트 설계와 구현이 테스트 실행의 일부로 이루어지거나 기록된다. 탐색적 테스팅은 분석에서 생성되는 테스트 차터를 기반으로 이루어지며 탐색적 테스트는 설계되고 구현되면서 바로 실행된다.
(6) 테스트 실행
테스트 스위트를 실행 일정에 따라 실행한다.
- 테스트 항목, 대상, 도구, 웨어 등 고유번호(id)와 버전 기록
- 테스트 수동 혹슨 실행 도구로 실행
- 기대 결과와 실제 결과 비교
- 이상 현상 분석해 원인 파악
- 관찰한 장애 기반 결함 보고
- 테스트 실행 결과 기록
- 이상 현상 또는 계획된 테스팅 일부로 테스트 활동 반복
(수정 테스트 재 실행, 확인 테스팅이나 리그레션 테스팅) - 테스트 베이시스, 컨디션, 케이스, 프로시저, 결과 간 양방향 추적성 검증
(7) 테스트 완료
테스트 완료 활동은 데이터를 수집해 경험, 테스트웨어, 기타 관련 정보를 축적하는 활동 소프트웨어 시스템을 릴리즈 했을 때, 테스트 프로젝트 완료 또는 취소 시, 애자일 반복 주기가 끝났을 때, 특정 테스트 레벨 완료했을 때, 유지보수 릴리스 완료 시 등 프로젝트 마일스톤 시점에서 일어난다.
- 모든 결함 보고 처리 완료, 미해결 결함에 수정 요청서 또는 프로젝트 백로그 항목 생성 점검
- 테스트 요약 보고서 생성
- 테스트 환경, 인프라, 기타 테스트웨어 마무리 및 보관
- 테스트웨어를 유지보수팀, 다른 팀 등에게 인계
- 교훈을 얻기 위해 테스트 분석 해 수정해야 하는 사항 판단
- 테스트 프로세스 성숙도 개선을 위해 수집된 정보 활용
1.4.3 테스트 작업 산출물
'테스트 작업 산출물'은 테스트 프로세스의 일부로 생성된다. 조직마다 테스트 프로세스 구현하는 방법이 다르듯이, 생성되는 작업 산출물의 유형, 관리 방법, 부르는 명칭 모두 다양하다.
테스트 계획 작업 산출물
하나 이상의 테스트 계획이 포함되며 테스트 계획은 테스트 베이시스에 대한 정보를 포함한다. 테스트 베이시스는 추적성 정보를 통해 다른 작업 산출물 뿐만 아니라, 모니터링과 제어에 사용되는 종료 조건(완료 조건)과도 연결된다.
테스트 모니터링과 작업 산출물
이 산출물은 보통 지속적, 장기적으로 생성되는 테스트 진행 현황 보고서와 다양한 테스트 완료 마일스톤에서 생성되는 테스트 요약 보고서와 같은 여러 형태의 테스트 보고서를 포함한다. 작성을 기준 테스트 진행 상황을 제공한다. 실행 결과 나오면 요약해 포함해야 한다.
테스트 분석 작업 산출물
분석 통해 식별되고 우선 순위 선정된 테스트 컨디션은 테스트 분석 작업 산출물에 속한다. 이상적으론 각 테스트 컨디션과 이것이 커버하는 테스트 베이시스 요소와 양방향 추적성이 성립되어야 한다. 탐색적 테스팅에서는 테스트 분석 중 차터를 생성할 수 있다. 테스트 분석에서 테스트 베이시스의 결함을 발견, 보고할 수 있다.
테스트 설계 작업 산출물
테스트 설계 결과로 분석에서 정의한 컨디션을 실행할 수 있는 케이스와 세트가 만들어 진다. 입력 데이터와 기대 결과로 사용할 값이 고정되지 않은 테스트 케이스를 먼저 설계하는 것이 좋다. 이런 케이스는 결과 값을 바꿔가며 다양한 테스트 주기에 재활용 가능하며 범위를 충분히 기록할 수 있다. 케이스와 이가 커버하는 테스트 컨디션 간의 양방향 추적성이 성립되어야 한다.
- 필요한 테스트 데이터의 설계나 식별
- 테스트 환경 설계
- 인프라와 도구 식별
테스트 구현 작업 산출물
- 테스트 프로시저와 배열
- 테스트 스위트
- 테스트 실행 일정
테스트 구현이 끝나면 케이스와 컨디션을 통해 프로시저와 베이시스 개별 요소 간 양방향 추적성을 확인함으로써 커버리지 조건 달성 여부를 확인한다. 테스트 구현이 도구 사용 시 도구소 생성되는 작업 산출물을 포함한다. 서비스 가상화나 자동 테스트 스크립트 경우 해당한다. 테스트 구현 결과로 데이터와 환경을 구현 및 검증할 수 있다.
테스트 데이터는 케이스의 입력값과 기대값에 확정 값을 할당하는 데 사용한다. 해당 값의 사용에 세부적인 지침으로 확정된 값은 상위 수준 테스트 케이스를 하위 테스트 케이스로 변화시킨다. 테스트 대상의 다른 릴리스에 대해 같은 상위 수준 테스트 케이스 실행시 다른 테스트 데이터를 사용할 수 있다. 기대 결과값은 테스트 오라클을 통해 식별할 수 있다.
탐색적 테스팅은 테스트 실행 중 산출물을 생성할 수 있지만, 탐색적 테스트 중 무엇이 문서로 기록되는지는 상황에 따라 상당히 달라진다. 분석에서 정의한 컨디션은 테스트 구현 중 추가로 개선할 수 있다.
테스트 실행 작업 산출물
- 개별 테스트 케이스나 프로시저 상태에 대한 문서(합격, 불합격 등)
- 결함 보고서
- 테스팅에 사용한 항목, 대상, 도구, 테스트웨어 등
테스트 실행 끝나면 테스트 프로시저와 양방향 추적승으로 테스트 베이시스 개별 요소의 상태에 대해 판단하고 보고한다. 그 결과로 커버리지 조건 충족 여부를 검증할 수 있으며, 보고한다.
테스트 완료 작업 산출물
테스트 요약 보고서, 차후 프로젝트나 반복주기 개선을 위한 액션 아이템, 수정 요청서, 제품 백로그 항목, 완성된 테스트웨어 등
1.4.4 테스트 베이시스와 테스트 작업 산출물 간 추적성
테스트 작업 산출물은 다양한다. 효과적인 테스트 모니터링과 제어를 구현하려면 테스트 프로세스 전반에 걸쳐 베이시스의 개별 요소에 추적성을 확립하고 유지하는 것이 중요하다. 좋은 추적성은 커버리지에 대한 평가를 가능하게 할 뿐만 아니라 다음 장점도 제공한다.
- 수정으로 인한 영향 평가 가능
- 테스팅에 대한 감사 가능
- IT통제 조건 충족 가능
- 테스트 베이시스 개별 요소 상태 정보 포함함으로써 테스트 진행 상황 보고 및 요약 정보 제공 가능
- 테스팅의 기술적 내용을 이해 가능한 형태로 전달 가능
- 비즈니스 목표 대비 제품 품질, 프로세스 역량, 진행 상황 등 보고 가능
1.5 테스팅의 심리학
1.5.1 인간 심리학과 테스팅
요구사항 리뷰나 스토리 개선 세션에서 결함 식별하거나 동적 테스트 실행 중 장애 발견 시 비판 오해 받을 소지가 있다. 확증 편향은 현재 가지고 있는 믿음과 맞지 않는 정보를 받아들이기 어렵다. 다른 인즈 편향도 있다. 나쁜 소식 전달이 힘든데, 테스팅 정보는 나쁜 소식을 포함하는 경우가 많다.
이런 이유로 테스팅을 파괴적 활동으로 간주한다. 이런 편견을 줄이기 위해 결함과 장애에 대한 정보는 건설적인 방법으로 전달할 필요가 있다. 긴장을 완화하고 이는 정적, 동적 테스팅 모두에 해당한다.
테스트와 관리자는 결함, 장애, 결과, 리스크 등 효과적으로 전달하기 위해 대인 관계 기술을 가질 필요가 있다. 다음은 의사소통을 더 잘할 수 있는 방법에 대한 예제이다.
- 다툼보단 협력, 공통 목표 인식
- 테스팅 이점 강조. 역량 향상하는데 도움, 품질 리스크 감소
- 테스트 결과를 중립적이며 사실 기반 방법으로 전달. 비판 금지. 객관적이고 사실 기반 결함 보고서와 리뷰 결과서 작성
- 어떤 느낌 받을 지, 해당 정보 부정적 반응 이유 뭔지 이해
- 전달 받은 내용 이해했는지 확인
올바른 테스트 목표 세트 명확하게 정의는 심리학적 중요한 역할. 테스터도 개인 성향 최대한 배제하고 목표와 부합하려고 하는 자세 매우 중요
1.5.2 테스터와 개발자의 사고방식
개발자와 테스터는 생각하는 방식이 달라진다. 개발 일차 목표는 제품 설계와 구축이다. 테스팅의 목적은 제품에 대한 밸리데이션(확인)과 베리피케이션(검증), 릴리스 전 결함 발견이다. 테스터는 호기심, 전문적 비평, 비판적 시각, 세밀한 것에 주목, 긍정적 의사소통이 있어야 한다. 테스터 사고방식은 경험을 쌓아감으로 점차 확대되고 성숙해지는 경향을 가진다. 개발자는 확증편향 때문에 오류 인지가 어렵다.
개발자는 자신의 코드를 직접 테스트 할 수 있다. 소프트웨어 개발 수명주기 모델에 따라 테스트 구성 및 활동 방식이 다르다. 독립적 테스터가 하면 결함 발견 효과가 높일 수 있는데 이는 규모가 크고 복잡하며 안전 필수 시스템의 경우 더 중요하다. 독립 테스터는 다른 확증 편항을 가지기에 다른 관점을 갖는다.