Serach

2013년 10월 10일 목요일

소프트웨어 테스트



테스트는 에러를 찾기 위해 프로그램을 실행하는 프로세스다.

발견 못한 에러를 찾을 확률이 높아야 좋은 테스트 케이스다.

성공적인 테스트 케이스는 발견하지 못한 에러를 찾는 테스트 케이스다.

프로그램의 신뢰성을 정량화하는 것은 매우 어렵다.


프로그래머는 자동화된 테스트를 시작할때 심리적 변화를 경험한다.
빨리 만들고자하는 내부로부터의 압박이 있고, 
짜증나는 버그를 가능한 빨리 수정하고 싶어하는 경향이 있다.
이런 압박 때문에 발견된 에러를 수정할때 많은 에러를 범하는 경우가 많다.


테스트 원칙

원칙 1: 테스트 케이스의 필요한 부분은 예상 출력이나 결과에 대한 정의다.

인간의 눈은 원하는 것만 보려고 한다.

1. 프로그램 입력 데이터에 대한 기술
2. 입력 데이터에 대한 프로그램의 정확한 출력에 대한 기술


원칙 2: 프로그래머는 자신의 프로그램 테스트를 피해야 한다.

건설적으로 설계하고 갑자기 프로그램을 파괴적인 시각으로 바라보기 힘들다. 


원칙 3: 프로그래밍 조직은 자신들의 프로그램을 테스트하지 말아야 한다.

원칙 4: 테스트 결과를 철저하게 조사해야 한다.

원칙 5: 유효하고 예상 가능한 입력 조건에 대한 테스트 케이스 작성은 
        물론, 무효하고 예상치 못한 입력 조건에 대해서도 테스트 케이스를 작성해야 한다.

원칙 6: 프로그램이 해야 할 것을 하지 않는지에 대한 조사도 중요하지만, 프로그램이 하지 말아야 할것까지 하는지도 찾아내야한다.

원칙 7: 한 번 사용하고 버리는 프로그램이 아니라면, 사용하고 버리는 테스트 케이스를 만들면 안된다.

원칙 8: 에러를 발견하지 못할 것이라는 암묵적인 합의하에 테스트 수행 계획을 작성하면 않된다.

원칙 9: 프로그램의 한 섹션에 많은 에러가 있을 가능성은 그 섹션에서 발견된 에러 수에 비례한다.

에러는 밀집돼 발생한다. 일반적인 프로그램에는 특정 섹션에 에러가 몰린다.

에러가 많이 발견되는 섹션에 초점을 맞춰 추가 테스팅 노력을 기울여야한다.


원칙 10: 테스팅은 극도로 창의적이고 지적인 도전이다.



-- 인간 기반의 테스팅 방법

코드 인스펙션(Code Inspection)
인스펙션 팀은 4인으로 구성 한명은 중재자이여야 하며,
중재자는 프로그램 개발자가 아니며 프로그램의 세부 사항에 익숙할 필요는 없고 중재자의 의무는 다음과 같다.
* 인스펙션 회의자료 배포 및 일정 관리
* 회의 주재
* 발견한 에러 기록
* 나중에 수정된 에러 확인

중재자는 품질관리 엔지니어
프로그래머 한명
나머지는 직접 개발하지 않는 설계자나 테스트 전문가

진행순서
1. 프로그래머는 프로그램 로직을 문장 단위로 읽는다. 토론중 다른 참가자는 질문을 해야하고 에러 존재 여부를 결정한다
   그 중 프로그래머가 가장 많은 에러를 발견한다.
2. 일반적인 프로그래밍 에러 체크리스트에 따라 프로그램을 분석한다.
- 데이터 참조 에러
: 설정 안된 변수 사용?
: 경계 내 첨자?
: 정수가 아닌 첨자?
: 허상 참조?
: 별명 사용 시 올바른 속성?
: 레코드와 구조 속성 일치 ?
: 비트 문자열 주소 연산?
: 올바른 기본 저장 속성?
: 모든 프로시저에 구조 정의 일치?
: 인덱싱이나 배열 첨자 조작시 하나씩 벗어나는 에러?
: 상속 요구 일치?
- 연산 에러
: 산술할 수 없는 변수의 연산?
: 혼합모드 연산?
: 길이가 다른 변수 연산?
: 할당 값보다 작은 변수 크기?
: 중간 값이 오버플로우나 언더플로우?
: 0으로 나눔?
: 부정확한 이진수?
: 변수 값이 의미 있는 범위 밖인가?
: 알고 있는 연산자 순서
: 올바른 정수 나눗셈?
- 데이터 선언 에러
: 모든 변수 선언?
: 알고 있는 기본 속성?
: 배열과 문자열의 적절한 초기화?
: 올바른 길이, 타입, 저장 클래스 지정?
: 저장 클래스와 일치하는 초기화?
: 비슷한 이름의 변수?
-비교 에러
: 일치하지 않는 변수 비교?
: 혼합모드 비교?
: 올바른 비교 관계?
: 올바른 불린 표현?
: 불린 표현과 비교 혼합?
: 2진 분수 값의 비교?
: 알고 있는 연산자 순서?
: 불린 표현의 컴파일러 평가?
- 제어 흐름 에러
: 다중 분기?
: 각 루프는 종료되는가?
: 프로그램은 종료되는가?
: 시작 조건 때문에 루프를 지나치는가?
: 지나가는 루프가 올바른가?
: 한 번씩 벗어나는 반복 에러?
: DO/END 문장 수, { } 갯수 일치?
: 누락된 결정?
: 출력 정보의 철자나 문법적 에러?
- I/O 에러
: 올바른 파일 속성?
: 올바른 OPEN ?
: 포멧 명세는 I/O 문장과 일치?
: 버퍼 크기는 레코드 크기와 일치?
: 사용 전 파일 열기 ?
: 사용 후 파일 닫기 ?
: End of File 조건 처리?
: I/O 에러 처리 ?
- 인터페이스 에러
: 입력 파라미터 수와 인수의 수 일치?
: 파라미터와 인수 속성의 일치?
: 파라미터와 인수 단위의 일치?
: 호출된 모듈에 전송되는 인수와 파라미터의 수의 일치?
: 호출된 모듈에 전송되는 인수의 속성과 파라미터의 단위 일치?
: 내장된 함수 인수의 올바른 수, 속성, 순서?
: 현재 시작 포인트와 관련 없는 파라미터 참조?
: 입력 전용 인수의 변경?
: 모든 모듈에서 전역 변수 정의 일치?
: 인수로 상수 전달?
- 기타 체크
: 상호 참조 리스트에서 참조되지 않는 변수?
: 예상되는 속성 리스트?
: 경고나 정보 메시지?
: 유효성을 위한 입력 확인?
: 누락된 기능?


이상적인 회의시간은 90~120분
보통 시간당 150개 프로그램 문장 속도로 진행
각 인스펙션은 하나이상의 모듈이나 서브루틴을 다룬다.
프로그래머는 방어적 태도를 취하면 프로세스는 효과가 떨어진다.
다시말해 프로그래머는 자존심을 버리고 긍적적이고 건설적으로 프로세스에 참여해야한다.
목적은 에러를 찾는것.
인스펙션의 결과는 비밀. 외부공개 X

워크스루
3~5명으로 진행
미리 회의 주제를 배포
참가자는 '컴퓨터 역할'을 한다.
테스터로 지정된 참가자는 프로그램이나 모듈의 입력값을 대표하는 문서로 된 테스트 케이스를 준비한다.
회의중 각 테스트 케이스는 생각으로 실행된다.
프로그램의 상태는 화이트보느나 종이에 기록
테스트 케이스보다는 회의를 진행하며 프로그래머에게 논리와 가정에 대해 질문한다.
테스트 케이스보다는 프로그래머에게한 질문에서 에러가 발견된다.
질문은 프로그래머보다는 프로그램에 대해 의견을 제시해야한다.

데스크 체킹
한 사람이 하는 익스펙션이나 워크스루로 볼 수 있다.
한 사람이 프로그램을 읽고, 에러를 체크하고, 테스트 데이터를 실행한다.

데스크 체킹은 워크스루나 인스펙션보다 비효율적이다. 하지만 하지 않는것보다는 낫다.

동료 평가
프로그램 테스팅과는 무관
익명의 프로그램에 대해 전반적인 품질, 유지보수성, 확장성, 사용성, 명확성을 평가하는 기법
이 기법의 목적은 프로그래머 자체 평가
한 프로그래머를 프로세스 관리자로 선출.
관리자는 6명에서 20명의 참가자를 선택
참가자는 비슷한 경력을 가지고 있어야함.
참가자는 자신의 프로그램중 리뷰할 2개를 선택한다. 하나는 가장 잘된것. 하나는 가장 품질이 낮다고 생각되는것.
프로그램이 선택되면 다른 참가자들에게 비공개 배포한다. 각 참가자는 4개의 프로그램을 리뷰
한 프로그램당 30분씩 리뷰, 리뷰 후 상대평가

다음 각 항목을 1~7점으로 답한다
* 프로그램은 이해하기 쉬운가?
* 상위 레벨 설계는 명확하고 타당한가?
* 하위 레벨 설계는 명확하고 타당한다?
* 프로그램은 변경하기 쉬운가?
* 작성된 프로그램 수준에 확신이 서는가?

또한 리뷰어는 일반적인 의견과 향상을 위한 제안을 한다.
리뷰가 끝나면 참가자는 익명 평가양식을 받는다.
참가자 전체는 전체 프로그램에서 자신의 프로그램 전체순위와 상세 순위 통계 요약을 받게 된다.
이 프로세스의 목적은 프로그래머가 자기 자신의 프로그래밍 기술을 자체 평가하기 위한 것이다.


---------------------------------------------------------------------------------


테스트 케이스 설계

가용한 테스트 케이스의 어떤 부분 집합이 많은 에러를 찾을 확률이 가장 높은가?

임의 데이터 입력은 일반적으로 효과가 가장 낮다.

'프로그램의 설계와 코딩이 어렵다고 생각했더라도 테스트하지 않았다면 아직 아무것도 안 한 것'

블랙박스 방법으로 테스트 케이스를 개발하고, 화이트박스 방법으로 필요한 테스트를 보충한다.




테스팅 기법 

문장 커버리지 - 화이트박스
프로그램의 각 문장을 실행하는 것

결정 커버리지 - 화이트박스
모든 결정(분기문이나 결정문 switch,do~while,if~else)은 참과 거짓 결과를 가져야 하며, 
결정내의 모든 문장도 최소한 한번은 실행되는 것

조건 커버리지 - 화이트박스
모든 조건은 가능한 결과가 최소한 한번은 실행되는 것

결정-조건 커버리지 - 화이트박스
결정 내의 모든 조건을 최소한 한번씩 만족하고 모든 결정의 결과를 최소한 한번씩 만족하여 
시작점을 최소한 한번씩 실행하는 것

다중조건 커버리지 - 화이트박스
결정에서 가능한 모든 조건 결과의 조합과 모든 시작점을 최소한 한번 실행





동등 분할 - 블랙박스
-미리 정의된 적절한 테스팅 목표를 만족하며 다른 테스트 케이스를 하나 이상 줄인다.
-가능한 다른 테스트 케이스의 큰 집합과 관계한다. 즉 가능한 큰 입력 값의 집합에 대해
 특정 입력 값의 집합으로 에러 유무를 알려준다.

같은 케이스를 식별하고 테스트 케이스를 정의한다.
즉, 필요한 테스트 케이스 수를 가능한 최소화 하면서 서로 다른 입력 고려사항을 다뤄야 한다.

경계 값 분석 - 블랙박스
- 대표하는 값으로 동등 클래스의 임의 요소를 선택하기 보다 경계 값 분석에서는 
   동등 클래스의 경계에 있는 값을 테스트 대상이 되는 요소로 선택한다.
- 입력 조건에만 초점을 맞추기보다 결과 영역도 고려해 테스트 케이스를 도출한다.


에러 추측 - 블랙박스
- 직감과 경험으로 가능한 형태의 에러를 추측하고, 에러를 밝혀내기 위해 테스트를 작성한다
- 직감과 임의의 프로세스이기 떄문에 절차를 말하기 어렵다.


---------------------------------------------------------------------------------


테스트의 종류

- 모듈 테스팅
모듈을 정의하는 기능 명세나 인터페이스 명세와 기능을 비교하기 위해.
모듈이 명세를 만족하는가를 보여주는게 아니라 명세에 모순됨을 보여주는 것이다.
화이트박스 로직 커버리지기준을 달성한다.


- 기능 테스팅
프로그램 외부 명세와 차이를 찾는다.
블랙박스 테스팅. 
가이드 라인도 기능테스팅에 적절
불일치와 에러를 찾는것, 외부 명세 충족 여부 확인을 하는 프로세스가 아니다.

- 시스템 테스팅
가장 잘못 알고 있고 어려운 테스팅
시스템 테스팅의 목적은 시스템이나 프로그램을 원래 개발 목적과 비교하는 것이다
시스템 테스팅은 프로그램이 전체적으로 개발 목적을 충족하지 않음을 찾아내는 프로세스이다
문서화되고 측정 가능한 제품의 개발 목적이 없다면, 본질적으로 시스템 테스팅은 할 수 없다.

설계 방법론이 존재하지 않아 풍부한 창의력 필요 15가지 종류
1. 편의 테스팅 - 사용자는 저장위치와 범위를 지정 할 수 있어야...
2. 볼륨 테스팅 - 대량의 데이터 처리
3. 스트레스 테스팅 - 과도한 부하나 스트레스를 부과해 작용 여부 확인
4. 사용성 테스팅 - 인간적인 요소 또는 사용성 문제를 발견하려는 시도
5. 보안성 테스팅 - 보안 목적을 토대로 일련의 절차를 거쳐 프로그램의 보안기능을 파괴하는 테스트
6. 성능 테스팅 - 일정한 부하와 설정 조건에서 응답시간과 처리율과 같은 특성으로 표현
7. 스토리지 테스팅 - 주, 보조 메모리 크기나 임시 파일이나 조각난 파일의 크기 등과 같은 용량 목표값 확인
8. 구성 테스팅 - 운영체제, 디비, 메시지 스위칭, 입/출력장치, 통신, 메모리 등 장치 유형마다 최소구성과 최대 구성을 테스트해야한다.
예를 들면 다중 운영체제를 지원하도록 설계되었다면 프로그램이 지원하는 모든 운영체제에서 테스트
9. 호환성 테스팅 - 결함이 있는 일부 시스템을 대체하기 위해 개발하는경우. 기존 시스템과 호환되며 신규로 전환되는 것을 테스트
10. 설치성 테스팅 - 설치 절차를 테스트
11. 신뢰성 테스팅 - 신뢰성 목표가 구체적으로 명시돼 있다면 구체적인 신뢰성 테스트를 준비. 
평균 고장 간격이나 사용과정에서 결함 12개 이하등의 목표가 있을 수 있다.(참고 : 귀납적 공리)
12. 회복 테스팅 - 에러 복구 방법을 기술한 회복성 테스팅. 시스템이 정상적으로 회복되는지 확인을 위해 고의로 에러를 주입하기도 한다.
13. 서비스 가능성 테스팅 - 덤프, 진단기, 디버깅의 평균 시간, 유지보수 절차, 내부 논리 설명서의 품질등 부가적인 서비스 지원목표
14. 문서 테스팅 - 사용자 문서에 설명된 모든 예제를 테스트 케이스로 만들어 프로그램을 테스트
15. 절차 테스팅 - 사용자의 개입이 필요한 자동화 되지 않은 대규모 시스템의 테스트

* 볼륨테스트는 대량의 데이터를 처리 할 수 있는지를 확인하는 것이고
   스트레스 테스트는 시간당 처리 속도를 유지 할 수 있는지 여부를 확인하는 것이다.

- 인수 테스팅
테스트 대상 프로그램의 초기 요구 사항 및 현재 사용자의 요구를 비교하는 프로세스
일반적으로 프로그램의 고객이나 최종 사용자가 수행하는 특이한 형태의 테스팅

- 설치 테스팅
시스템의 각 파트가 모두 존재하는지, 모든 파일이 생성됬고 해당 파일이 필수적인 내용을 담고 있는지, 
하드웨어 구성이 적절한지 테스트



---------------------------------------------------------------------------------


테스트 완료 기준

경제적 논리에 따라 언젠가는 테스트가 끝나야 한다.

1. 정해진 기간이 끝나면 테스트 종료
2. 모든 테스트 케이스를 실행해도 더 이상 결합이 발견되지 않으면 테스트 종료, 
   즉 테스트에 더 이상의 의미가 없어지게 되면 테스트 종료

위의 두가지 조건 보다 나은 조건 기준

1. 테스트 케이스는 다중조건 커버리지와 모듈 인터페이스 명세 경계 값 분석을 만족해야하며, 
    작성된 테스트 케이스를 모두 실행했을때 결함이 발견되지 않아야한다.
2. 테스트 케이스를 원인결과 그래핑, 경계 값 분석, 에러 추측 등 의 기법으로 작성하고 
    작성된 테스트 케이스를 모두 실행했을때 결함이 발견되지 않아야한다.


---------------------------------------------------------------------------------


디버깅


- 무차별 디버깅
저장된 덤프를 이용한 디버깅
프로그램 코드에서 화면 프린트 구문을 이용한 일반적인 디버깅
자동화 디버깅 도구를 이용한 디버깅

가장 일반적이지만 가장 비효율적이다.
무차별 방법의 일반적인 문제는 에러의 원인에 대해 생각하는 과정을 무시하는 것이다. 바람직하지는 않다.

디버깅과 미스터리 소설은 유사점이 많다.
겉으로 보기에는 하찮고 작은 것을 퍼즐 맞추듯 종합해 문제를 풀어낸다.
디버깅은 길을 막거나 건물을 수색하는 무차별 방법이 아니다.

무차별 디버깅은 다음의 경우에만 사용하도록 권한다.
다른 모든 디버깅 방법이 통하지 않을 경우
다음에 설명할 지적 활동 과정의 대체가 아닌 보완책으로 사용할 경우

- 귀납적 디버깅
어떤 상황의 세부적인 것으로부터 전체를 유추하는 사고 과정.
하나 이상의 테스트 케이스 실행 결과나 에러 증상과 같은 단서로 부터 시작해 그 단서간의 관련성을 찾는다

데이터 수집 -> 데이터 구성 -> 관계성 연구 -> 가설 고안-> 가설 입증-> 에러 수정


- 연역적 디버깅
어떤 일반적인 이론이나 전제로부터 출발해 제거와 정제 과정을 거쳐 결론에 도달하는 것.

가능한 원인 열거 -> 제거 절차 사용 -> 남은 가설 정제 -> 남은 가설 증명 -> 에러 수정

- 역추적에 의한 디버깅
로직을 벗어난 지점을 발견할 때까지 프로그램의 로직을 따라가며 부정확한 결과를 역추적하는 것.

- 테스팅에 의한 디버깅
테스트 케이스를 사용해 디버깅을 위한 테스트를 추가해 디버깅한다
귀납적,연역적 디버깅과 연계해 가설을 생성하고 증명하는데 필요한 정보를 얻고자 자주 사용된다.

 ---------------------------------------------------------------------------------

디버깅 원리

생각하라.
디버깅은 문제 해결 프로세스이다. 
에러 증상 관련 정보를 지적으로 분석하는 것이 가장 효과적인 디버깅 방법이다.


난국에 부딪히면 잠시 쉬어라
인간의 잠재의식은 강력한 문제 해결사이다. 
잠시 문제를 잊어버리면 잠재의식이 문제를 해결하거나 의식이 증상의 새로운 검토를 할 수 있게 맑아진다.


난국에 부딪히면 문제를 다른 사람에게 설명하라
다른 사람에게 설명하다보면 문제가 정리되며 듣는 사람의 도움 없이도 갑자기 해결방법을 찾을 수 있다.


차선책으로 디버깅 도구를 사용하라
보조 도구로 디버깅 도구를 사용하라


실험은 피하되 최후의 수단으로 사용하라
문제를 해결하기 위해 프로그램을 실험적으로 변경하려는 시도는 피하라.
이와 같은 방법은 완전히 무계획된 맹목적인 희망일뿐 디버깅이 아니다.
성공률이 낮을 뿐만 아니라, 많은 경우 프로그램의 새로운 버그를 추가한다.


---------------------------------------------------------------------------------



에러 수정 기법

버그 하나가 있는 곳엔 다른 버그가 있을 가능성이 높다.
프로그램의 특정 부분에서 에러를 발견하면, 그 부분에 다른 버그가 있을 가능성이 높다.


에러의 증상이 아닌 에러를 고쳐라
에러의 일부 증상이 아닌 원인을 찾아 확실히 에러를 제거하라


정확히 수정될 확률은 100%가 아니다
구문을 수정하기 위한 구문은 프로그램의 원래 코드보다 훨씬 더 에러 발생률이 높다.
이러한 이유로  에러 수정은 반드시 테스트해야 하고, 원래 프로그램보다 더 엄격하게 테스트해야 한다

프로그램이 커지면 정확히 수정될 확률은 낮아진다
에러를 잘못 수정해서 발생하는 에러의 비율은 증가한다.
큰 프로그램에서 발견되는 버그 6개 중에 하나는 이미 수정했던 곳에서 발생한다.

수정 과정에서 에러를 유발할 수 있다
부정확한 수정이 외관상 적확한 수정처럼 보일 수 있음은 물론이고,
원하지 않는 부작용으로 인해 부정확한 수정이 외관상 정확한 수정처럼 보일 수 있따.

에러 수정 프로세스에서 잠시 설계 단계롤 되돌아갈 필요가 있다
에러 수정은 설계의 한 형태임을 알아야 한다. 
설계 과정에서 사용된 절차와 방법론 그리고 형식 모두를 에러수정 프로세스에도 적용해야한다.

---------------------------------------------------------------------------------

에러 분석
프로그램 디버깅이해에 있어 마지막 사항은 디버깅이 프로그램의 에러 제거 가치 외에도 
또 다른 효과를 가져올 수 있다는 것이다
디버깅은 아직 드러나지 않은 소프트웨어 에러의 본질에 대해 뭔가를 알려줄 수 있다.
미래의 설계, 코딩, 테스팅 과정을 개선하는 측면에서 피드백을 제공한다.
- 어디서 에러가 생성됐는가?
- 누가 에러를 만들었나?
- 무엇이 잘못됐는가?
- 어떻게 하면 에러를 예방할 수 있을까?
- 왜 에러를 초기에 발견하지 못했을까?

- 어떻게 하면 에러를 초기에 발견할 수 있을까?




댓글 없음:

댓글 쓰기