|
1.1 소프트웨어 테스트 중요성
- 높은 신뢰성이 요구되는 시스템에도 소프트웨어가 차지하는 비중이 점차 커지고 있다.
• 은행이나 증권회사에서 고객들의 계좌나 주식거래를 관리하는 시스템, 병원에서 환자를 모니터링하고 치료하는 기기,
원자력발전소를 운영하는 시스템 등
• 이메일, 온라인 쇼핑, 인터넷 뱅킹, 개인 홈페이지 등을 가능케 하는 인터넷의 핵심도 소프트웨어
• 시스템들이 오작동한다면 경제적, 사회적 손실 뿐만 아니라 막대한 인명 피해까지도 발생할 수 있다
• 시스템이 오작동하지 않도록 하기 위해 시스템에서 소프트웨어가 차지하는 비중이 높아진 만큼 소프트웨어 품질이 중요하게
관리되어야 한다.
- 소프트웨어의 품질을 제고하는 가장 일반적이면서 실질적인 방법 중에 대표적인 것으로 소프트웨어 테스트가 있다.
• 소프트웨어 테스트는 소프트웨어의 오류를 검출하는 가장 전통적이면서 널리 사용되는 방법
• 소프트웨어 테스트의 중요성을 알기 위해서는 충분한 테스트가 수행되지 않은 제품을 출시한 후 소프트웨어 오류가
발생하였을 때 어떠한 결과가 초래되는가 살펴 볼 필요가 있다. 다음은 소프트웨어 오류로 인해 발생한 경제적/인명적 피해
사례들이다.
|사례 1| 아리안5 로켓 폭발 사고
아리안5 로켓의 전신인 아리안4 로켓에서 사용했던 항법 패키지(Navigation package)와 새로운 아리안5 로켓 시스템간의 호환성 문제로 판명되었으며 이 항법 패키지를 아리안5 로켓 시스템에 적용하는 과정에서 새로운 시스템과의 상호운영성, 안정성, 신뢰성 등에 대한 충분한 테스트를 수행하지 않은 것으로 밝혀졌다.
|사례 2 | 미국 덴버 개항 지연 사고
|사례 3| 에어버스 320 추락사고
비행 모드가 전환될 때 비행기의 실제 고도가 아닌 이미 기억되어 있는 고도를 메모리로부터 읽어 들여 표시하는 경우가 종종 있었다고 한다.
1.2 소프트웨어 테스트 정의
- 테스트는 프로그램 또는 시스템이 해야 되는 일을 실제로 수행하는 지를 확인하는 과정 [Hetzel 73]
- 소프트웨어가 도출한 결과가 정확한지 확인하기 위해 소프트웨어를 실행하는 과정 [Glass 79]
- 에러를 발견할 목적으로 프로그램을 실행하는 과정 [Myers 79]
- 프로그램 테스트는 오류가 존재함을 보일 수는 있지만 오류가 없음을 보일 수는 없다. [Dijkstra 72]
- 테스트는 소프트웨어 품질의 척도 [Hetzel 85]
- 시스템이나 컴포넌트를 명시된 조건에서 동작시켜 그 결과를 관찰하거나 기록하여 시스템이나 컴포넌트의 어떤 측면을
평가하는 과정 [IEEE/ANSI 90]
이와 같은 정의들을 바탕으로 소프트웨어 테스트는 다음과 같은 목적을 달성하기 위한 모든 활동들로 요약할 수 있다.
- 프로그램의 오류를 발견하기 위해 프로그램을 실행하는 과정
- 품질 평가를 위해 프로그램을 실행하는 과정
- 프로그램의 신뢰도를 높이기 위해 프로그램을 실행하는 과정
- 오류를 발견하거나 오류의 발생을 미연에 방지할 목적으로 프로그램이나 문서들을 분석하는 과정
이와 같은 정의들은 프로그램을 실제로 실행한다는 전제 조건을 가지고 있다.
검토(Review), 인스펙션(Inspection) 및 워크쓰루(Walkthrough)와 같은 명세서나 코드를 실제로 실행하지 않고 검토하는 정적 분석 방법(Staticanalysis)들도 테스트 범주로 포함된다.
1.3 소프트웨어 에러, 결함 그리고 오작동
- 프로그램이 의도한 대로 동작하지 않는 현상 또는 그 원인을 나타내는 용어로서 오류, 에러, 결함, 버그 등 다양한 용어들이
사용
• 에러(Human error 또는 Mistake), 결함(Fault 또는 Defect), 오작동(Failure) 등의 용어를 구분하여 사용하지 않고 모두
오류라는 말로 통일하여 사용할 것임
• 에러(Error) : 사용자 요구사항을 잘못 파악하거나 잘못 이해할 때 발생하는 실수,
타이핑 실수나 프로그램의 명령어를 잘못 이해하여 코딩하는 경우도 이에 포함,
에러는 사람에 의해 발생하기 때문에 실수(Mistake)라고도 함,
프로그램의 올바르지 않은 내부 상태(예를 들면, 선행 조건, 후행 조건, 프로그램의 무결성이 위배된 프로그램
상태)
• 결함(Fault) : 에러가 표현된 것으로 두 종류의 결함이 있는데 잘못된 정보를 프로그램 코드에 반영하는 경우와
올바른 정보를 누락시키는 경우이다.
다른 용어로 'Defect' 라고도 한다.
에러를 발생시키는 프로그램의 부분
• 오작동(Failure) : 결함이 실행될 때 오작동이 발생할 수 있다. 오작동은 프로그램의 실행 결과와 올바른 결과와의 관찰
가능한 차이를 말한다.
오작동은 결함에 의해 발생하지만 결함이 있다고 해서 반드시 오작동이 발생하지는 않는다.
프로그램이 명세와는 다르게 동작하는 것이 외부에서 관찰되는 상황
그림 1.1은 에러, 결함, 오작동 간의 상관 관계를 보여준다. 프로그래머가 에러를 범하여 프로그램에 결함이 삽입되고 이 결함으로 인해 프로그램 실행 시 오작동이 발생하게 된다. 프로그램의 동작 결과가 정상인지 오작동인지는 명세로부터 추출된 예상 결과와 프로그램 동작의 실제 결과를 비교함으로써 알 수 있다. 예를들어, 다음과 같은 요구사항 R이 있고 이를 코드 C처럼 구현했다고 가정하자.
R : 속도를 출력하라.
속도(s)는 거리(d)를 시간(t)으로 나눔으로써 알 수 있다.
C:s=d/t; print s;
이 경우에 다음과 같은 에러, 결함, 오작동이 발생된다
• 에러 시간이 0인 경우에 어떻게 처리해야 할지를 고려하지 않았다.
• 결함 시간이 0이 되는 경우(즉, t = 0)를 처리하는 코드가 없다.
• 오작동 시간이 0이 되는 경우(Divided by zero) 예외(Exception)가 발생한다.
이 예에서 보듯이 결함의 원인은 에러이고 오작동의 원인은 결함이다. 즉, 프로그램의 오작동이 발생하기 위해서는 프로그램에서 결함이 있는 코드가 실행되어야 한다는 것을 알 수 있다. 그러므로 효과적인 테스트를 수행하기 위해서는 프로그램이 정상적으로 동작하지 않을 가능성이 높은 부분을 파악할 수 있어야 한다. 이러한 의미에서 위의 예에서는 시간이 0인 경우를 테스트하는 것이 좋은 테스트라 할 수 있다.
그러나 결함이 있는 부분이 실행된다 할지라도 오작동이 발생하지 않는 경우도있다. 이러한 경우를 구체적으로 살펴보기 위해, 한 개의 정수를 입력으로 받아 입력 값의 두 배를 계산하여 출력하는 프로그램을 살펴보자.
int double (int param)
{
1 : int retVal=0;
2 : retVal = param*param; // 프로그램 결함 부분
3: return retVal;
}
여기서 오작동의 원인은 에러이며 결함은 에러의 원인이 된다. 테스트를 통해 오작동이 관찰되면 디버깅 중에 에러 상태가 관찰되고 이를 유발하는 프로그램의 코드 부분(결함)을 찾아 제거한다. 예를 들어, 위의 double 프로그램의 입력으로 '3' 을 주었다면 2번 문장을 실행한 후에 변수 retVal은 '6' 대신에 '9' 를 가질 것이다. 이는 에러 상태를 나타내며 이는 연산자 '+' 대신에'를 사용한 결함 때문에 발생한 것이다. 만약 이 때문에 프로그램이 제 기능을 다하지 못한다면 오작동이 발생했다고 볼 수 있다.
위의 프로그램에서 프로그래머가 실수로 2번 문장에서 덧셈 연산자(+) 대신에 곱셈 연산자(*)를 사용하였다. 이러한 에러 때문에 2번 문장에 결함이 생겼다. 만약 테스트 시 입력값으로 '2' 를 사용한다면 결함이 있는 부분, 즉 2번 문장이 실행된다 할지라도 프로그램은 올바른 결과('4')를 출력하기 때문에 프로그램의 결함을 발견하지 못할 수 있다. 즉, 프로그램의 결함이 있는 부분을 테스트한다 할지라도 반드시 오작동(failure)이 발생하는 것은 아니다. 따라서 이러한 상황을 방지하기 위해서는 테스트 시 입력값 선정에도 주의를 기울여야 한다. 좋은 테스트는 대상 프로그램을 성공적으로 수행하게 하는 것이 아니고 아직 발견되지 않은 결함을 검출할 수 있도록 프로그램의 오작동을 발생시키는 것이다. 이를 위해서는 프로그램 오작동을 일으킬 수 있는 확률이 높은 테스트 시나리오 및 입력 값들을 선정하는 것이 매우 중요하다.
1.4 소프트웨어 오류의 원인
소프트웨어 오류가 발생하는 원인은 무엇일까? 오류를 효과적으로 발견하고 제거하기 위해서는 오류의 원인에 대해 알아볼 필요가 있다. 다음은 일반적으로 알려진 소프트웨어 오류의 주요 원인들이다.
- 요구사항의 잘못된 정의 : 고객의 요구사항이 불완전하게 반영되거나 틀리게 정의되는 경우에 해당한다. 요구사항의
불완전하다는 것은 필요한 모든 정보들이 요구사항으로 정의되지 못한 경우를 말한다. 예를 들어, 요구사항에 쇼핑몰
시스템에서 할인을 받을 수 있는 경우들이 모두 반영되지 않고 일부 항목이 누락되었다면 불완전한 요구사항이 된다.
뿐만 아니라, 실제 필요하지 않은 기능까지도 요구사항으로 정의하였다면 요구사항을 잘못 정의한 경우가 된다.
- 고객과 개발자간의 잘못된 의사소통 : 개발자가 요구사항 문서에 기술되어 있는 고객의 요구사항을 잘못 이해하거나
개발과정 중에 구두 또는 공식적인 문서를 통해 고객이 요구한 변경사항을 잘못 이해하는 경우에 해당된다.
- 고의적인 요구사항 미준수 : 때때로 개발자가 고의적으로 고객의 요구사항을 준수하지 않고 개발하는 경우가 있다.
이 경우의 예로 다음과 같은 상황들을 생각해볼 수 있다.
• 시간이나 예산 문제로 인해 개발자가 의도적으로 기능의 일부를 구현하지 않는 경우
• 고객과의 합의 없이 개발자가 임의로 개발 중인 시스템에 기능을 추가하는경우
- 설계 오류 : 소프트웨어 요구사항을 설계에 반영하는 과정에서 오류가 발생할 수 있다. 예를 들어, 소프트웨어의
요구사항을 잘못된 알고리즘이나 자료구조를 사용하여 표현한 경우가 이에 해당된다. 또는 예외상황, 경계값 등에 대한
처리 방법 설계가 누락되는 경우도 이에 해당된다.
- 코딩 오류 : 설계 문서를 잘못 이해하거나 프로그래밍 언어 또는 개발 도구에 익숙하지 않아 발생하는 오류 등이 포함된다.
- 문서나 코딩 표준에 따르지 않는 경우 : 일반적으로 개발팀은 코딩 스타일이나 문서양식 표준을 정의해 놓고 사용하는
경우가 많다. 만약 표준에 부합되지 않게 코드나 문서를 작성하게 되면 코드 이해가 쉽지 않아 검토 과정 또는 테스트
작업이 상대적으로 어렵게 되어 오류를 발견할 확률이 낮아진다.
- 미흡한 테스트 프로세스 : 테스트 계획을 수립할 때 소프트웨어의 어떤 기능에 대해 어떤 방법을 사용하여 테스트할
것인가를 결정하게 된다. 만약 이러한 계획과정이 체계적으로 이루어지지 않거나 아예 없다면 소프트웨어의 일부 기능들은
테스트 과정에서 전혀 고려되지 않을 수 있기 때문에 이 기능들과 관련된 오류들은 검출되지 않을 가능성이 높다.
또한 발견된 오류에 대해서 수정될 때까지 추적하고 모니터링하는 절차와 시스템을 갖추고 있지 않으면 테스트 시에
발견된 오류가 정상적으로 수정되었는지를 확인할 수가 없어 오류가 수정되지 않고시스템에 남아 있을 수도 있다.
이러한 원인들 중에서 가장 비중이 큰 오류의 원인은 명세 오류(고객의 요구사항을 잘못 파악하거나 요구사항 명세를 틀리게 정의한 경우 등)이다. 그림 1.2에 나타나 있는 오류 원인 분포에서 보는 것과 같이 소프트웨어 테스트에 대한 인식의 전환이 필요하다. 만약에 소프트웨어 테스트가 코딩 단계가 끝난 뒤에야 비로서 시작되는 활동이라고 생각한다면 엄청난 오류 수정 비용을 유발할 수 있다.
소프트웨어 테스트를 코딩 작업이 완료된 후에 수행하는 개발 프로세스의 한 단계로만 생각한다면 개발 초기 단계인 요구사항 단계에서 발생한 오류는 코딩 단계 이후인 테스트 단계 또는 고객에게 출시된 후에 발견될 가능성이 매우 높을 것이다. 아래의 그림 1.3은 소프트웨어 오류 발견 시점에 따른 오류 수정 비용을 보여준다. 예를 들어, 명세 오류가 개발 단계에서는 검출되지 못하고 고객에게 인도되어서야 검출된다면 이 오류가 명세 단계에서 검출되어 수정되었을 때보다 110배 정도의 비용이 소요된다고 알려져 있다. 결함이 나중에 발견됨으로써 낭비되는 비용을 줄이기 위해서는 소프트웨어 개발 단계에서 나오는 모든 산출물들을 제때에 적절한 방법으로 테스트하여 각 단계에서 발생하는 오류가 다음 단계로 전이되는 것을 방지하여야 한다. 요구사항 분석 및 정의 단계가 완료되면 인스펙션과 같은 검토 과정 등을 통해 요구사항 문서에 있는 결함을 검출(참고 1.2)하고 일정 품질 기준을 충족하면 다음 단계, 즉 설계 단계를 시작한다. 설계 단계를 끝내고 구현 단계로 가기 위해서도 마찬가지 과정을 거치도록 한다. 이처럼 소프트웨어 테스트를 개발 프로세스의 한 단계로만 인식하지 말고 개발 프로세스 전 과정에 걸쳐 수행되어야 하는 일련의 과정으로 인식하여야 한다.
완전성 | • 파악된 모든 요구사항이 기술되었는가? 누락된 요구사항은 없는가? • 모든 외부 하드웨어 및 소프트웨어, 통신 인터페이스에 대한 사항이 정의되었는가? • 발생 가능한 오류에 대한 정보가 기술되었는가? |
정확성 | • 요구사항들에 모순은 없는가? • 정보가 불필요하게 중복되지는 않는가? • 명확하게 정의된 용어들로 요구사항이 기술되어 있는가? • 모든 요구사항들이 구현 가능한가? |
품질 속성 | - 제품에 필요한 모든 품질 속성이 명확하게 기술되고 정량화되었는가? • 성능 목표가 적절하게 기술되었는가? • 보안 요구사항이 적절하게 기술되었는가? • 품질 속성들 간의 관계(Trade-off)가 기술되었는가? |
추적성 | • 각각의 요구사항이 명확하게 구별되는가? • 각각의 기능 요구사항에 대해 관련된 상위 레벨의 요구사항을 추적할 수 있는가? |
기타 | • 기술된 요구사항들이 설계 또는 구현과 관련된 내용이 아닌 실제 요구사항인가? • 국제화에 대한 이슈가 적절하게 기술되었는가? |
참고 1.2 | 요구사항 테스트
1.5 소프트웨어 테스트의 한계
- 완벽한 테스트는 없다!
- 테스트 데이터는 프로그램을 테스트하기 위해 선정된 입력 값들이다.
• 프로그램의 입력 영역은 무한히 크기 때문에 현실적으로 가능한 모든 입력 값들을 테스트 데이터로 선정할 수 없다.
예를 들어, 0부터 100사이의 두 개의 정수 값을 입력으로 하는 프로그램을 테스트해야 한다고 가정하자.
이 경우에 모든 가능한입력 조합의 수는 101*101=10,201개이다. 이렇게 간단한 프로그램을 테스트하더라도 10,000개가
넘는 테스트 데이터가 필요하다.
그림 1.4는 MS 워드 프로그램에서 글꼴에 관한 속성들을 설정하는 윈도우이다. 프로그램이 글꼴을 지정한대로 보여주는지를 확인하기 위해서는 모든 가능한 글꼴, 글꼴 스타일, 크기, 글꼴 색 및 효과 등의 조합을 고려하여 테스트 해야 한다.
이 기능을 테스트 하기 위해 필요한 테스트 데이터는 상상하기 어려운 조합이 될것이다. 예를 들어, 글꼴이 30개, 글꼴 스타일이 5개, 글꼴의 크기가 21개라고 가정하면 30*5*21=3,150개의 경우가 발생하며, 이에 추가적으로 글꼴 색, 밑줄 스타일 및 효과 등을 지정할 수 있으므로 엄청난 수의 조합이 필요하게 된다. 이 모든 경우를 테스트하는 것은 거의 불가능하다고 볼 수 있다.
이러한 현실적인 문제로 인해 테스트를 수행할 때는 가능한 모든 입력 값(조합)들 대신에 특정 조건을 만족하는 입력 값들만을 테스트 데이터로 사용한다. 이 때 사용되는 기준을 테스트 선정기준(Test selection criterion)이라고 한다.
그렇다면 가장 이상적인 테스트 선정기준은 무엇일까? 테스트 선정기준에 의해 선정된 테스트 데이터로 테스트를 완료한다면 프로그램에는 오류가 존재하지 않을까? 이물음들에 대한 해답을 구하기 위해서는 다음과 같은 테스트 데이터 집합(T)을 찾는 것이 가능해야 한다.
SUCCESS (T) => CORRECT (P)
프로그램(P)이 테스트 집합(T)에 대해 올바르게 수행된다면 프로그램(P)에는 오류가 없다.
이러한 특징을 갖는 테스트 집합은 가장 이상적인 테스트 집합임이 분명하다.그러나 이러한 테스트 집합을 만들어 내는 테스트 선정기준을 찾아낸다는 것은 불가능하다.
프로그램 테스트의 한계를 조금 더 쉽게 이해하기 위해 프로그램 테스트를 낚시와 비교하여 생각해 보자. 일정한 시간 동안 저수지에서 낚시를 할 때 물고기가 계속 잡히지 않는 경우를 생각해 보자. 이 경우 저수지에 정말 물고기가 없어서 잡히지 않을 수도 있고 물고기가 있는데 낚시 실력이 부족해서 잡히지 않을 수도 있다.그렇다면 낚시꾼이 이 저수지에는 물고기가 없다고 단정적으로 말하려면 어떻게해야 할까? 저수지에 있는 물을 전부 없애고 정말 물고기가 없는지를 살펴보는 방법 밖에는 없을 것이다. 현실적으로 불가능한 이야기이다.
낚시에서 사용되는 미끼를 테스트 데이터라고 생각하고 저수지의 물고기를 프로그램의 오류로 간주하여 생각해보자. 즉, 미끼가 다할 때까지 물고기가 잡히지않는 경우는 선정된 테스트 집합에 대해 프로그램이 모두 올바르게 실행되는 경우에 해당한다. 그러나 물고기가 잡히지 않는다고 저수지에 물고기가 없다고 단정적으로 말할 수 없듯이 이 경우에도 프로그램에 오류가 없다고 말할 수 없다. 이와 같은 프로그램 테스트 기술의 한계를 Dijkstra는 다음과 같이 표현하였다.
- “프로그램 테스트는 오류가 존재함을 보일 수는 있지만 오류가 없음을 보일 수 는 없다.” [Dijkstra 72]
테스트를 통하여 오류가 없음을 보일 수 없고 현실적으로 무한히 테스트를 수행할 수 없기 때문에 언제까지 테스트를 계속할 것인지를 결정해야 한다. 따라서 테스트를 완료하는 기준이 필요하며 이 기준을 만족할 때 테스트를 종료하면 된다.이 기준을 테스트 종료 기준(Test exit criteria)이라 한다.
테스트 종료 기준은 테스트 데이터를 선정할 때 사용하는 테스트 선정기준과 밀접한 관계가 있다. 일반적으로 주어진 테스트 선정기준을 만족하는 테스트 집합에 대해 프로그램이 올바르게 동작한다면 프로그램에 오류가 남아있다 하더라도 더이상 테스트를 수행하지 않는다.
1.6 소프트웨어 테스트 원칙
G. J. Myers는 “The Art of Software Testing”에서 소프트웨어 테스트를 수행할 때 기본적으로 따라야 할 원칙들을 소개하였다. 여기서는 그 중 꼭 명심해야 할부분에 대해 소개한다.
<원칙 1> 테스트는 반드시 해당 프로그램을 개발한 프로그래머 또는 개발팀과는 무관한 독립적인 그룹에 의해서도 수행되어야 한다.
- 프로그래머는 자신이 개발한 프로그램에 대해 많은 지식을 보유하고 있다는 점에서 오류를 효율적으로 발견할 수 있으나 몇 가지 이유로 인해 프로그래머의 테스트만으로는 부족하고 독립적인 그룹에 의한 테스트가 반드시 필요하다.
• 자신이 만든 결과물에 대해서는 방어적 경향을 보일 수 밖에 없는 심리를 가지고 있으므로 프로그래머도 자신이 작성한
프로그램에 대해서는 결함이 존재하지 않을 거라는 믿음을 가지게 된다. 그 결과, 프로그래머 자신이 작성한 프로그램을
테스트하게 되면 오류가 발견될 가능성이 상대적으로 낮아지게 된다. 또한 프로그래머가 요구사항을 잘못 이해하고
코딩을 한 경우 이와 관련된 오류는 해당 프로그래머가 테스트를 철저히 수행한다 할지라도 발견되지 않을 가능성이 높다.
이는 테스트도 코딩과 마찬가지로 같은 요구사항을 바탕으로 수행되어야 하는데 요구사항 자체가 잘못되어 있기 때문에
테스트도 잘못 수행될 가능성이 높기 때문이다.
<원칙 2> 테스트 작업을 능력이 가장 뛰어난 사람에게 할당하라.
- 소프트웨어 테스트의 잘못된 인식은 테스트 작업은 아주 쉽고 전문 기술 및 지식 없이도 수행할 수 있다고 생각하는 것이다.
• 현실적으로는 테스트를 수행할 때 매우 많은 문제들에 부딪히게 되며 이를 해결하기 위해서는 창조적이며 경험과 지식이
많아야 한다. 테스트가 쉽지 않은 가장 큰 이유는 기본적으로 테스트를 통해서 프로그램의 오류를 검출해야 하기 때문이며
이를 위해서는 양질의 테스트 케이스 집합을 설계하는 작업이 필요하기 때문이다.
여기서 양질의 테스트 케이스란 아직 발견되지 않은 오류를 검출할 확률이 높은 테스트 케이스를 말한다.
〈원칙 3> 오류가 발견되지 않을 것이라는 가정하에서 테스트 계획을 수립해서는 안 된다.
- 프로그램이 올바르게 동작한다는 사실을 입증하기 위해 테스트를 수행한다는 개념을 가지고 있다면 사람들은 오류를 찾을
확률이 많은 테스트 케이스를 설계하기 보다는 시스템이 제대로 동작하는 것을 증명하는데 초점이 맞추어진 테스트 케이스를
설계하게 된다. 그러나 테스트는 프로그램이 올바르게 동작한다는 것을 보여주는 작업이 아니고 오류를 발견하려는 의도로
프로그램을 실행하는 과정이기 때문에 프로그램이 잘 동작하지 않는다는 사실을 보여주려는 의도를 가지고 테스트 케이스를
설계해야 하고 이에 맞게 테스트 계획을 수립해야 한다.
〈원칙 4〉 유효한 입력값, 유효한 상태뿐만 아니라 유효하지 않은 입력값, 유효하지 않은 상태에 대해서도 테스트를 수행하라.
- 타당한 조건을 만족하는 입력들만 고려하여 테스트를 수행하는 경향이 있다. 그러나 많은 오류들은 프로그램이 예상하지 않은
방식으로 사용되는 경우에 발견된다. 예를 들어, 입력으로 정수 값을 받아들이는 프로그램에서 문자열을 입력하면 프로그램이
이를 적절히 처리하지 못하여 오류가 발생하는 것이 한 예이다. 특히 신뢰성이 매우 높게 요구되는 시스템인 경우, 예기치 않은
입력 또는 상태에 의해 시스템이 비정상적으로 종료되는 일이 없도록 발생 가능한 모든 입력 또는 상태에 대해 시스템이 적절한
반응을 하는지 테스트 해야 한다.
〈원칙 5> 프로그램의 특정 부분에 오류가 집중되어 있을 확률이 높다. 이는 다음과 같이 Pareto 원칙으로 설명될 수 있다.
- "프로그램 오류의 80%는 전체 모듈 가운데 20% 모듈에서 발생한다."
• 실제로 많은 프로그램에서 이러한 현상이 관찰되었다고 보고되었다. 프로그래머가 모듈을 작성할 때 최악의 상태로
코딩하여 특정 모듈을 오류투성이로 작성할 수도 있고 소프트웨어 설계나 구조 자체가 심각한 문제를 가지고 있어 발견된
오류들이 결국에는 동일한 원인에 의해 발생할 수도 있다. 이는 오류가 많이 발생하는 부분에 테스트 노력을 집중하는 것이
효과적이라는 것을 의미한다.
참고 1.3 | Pareto의 원칙
Pareto의 원칙이란 이탈리아 경제학자인 빌프레도 파레토(Vilfredo Pareto)가 1906년 이탈리아 토지의 80%를 인구의 20%가 소유하고 있다는 사실을 알아내고, 이 80%20% 사이의 상관관계를 다른 여러 분야에 적용하기 시작해 알려지기 시작했다. 이 현상은 다음과 같이 소프트웨어 분야에서도 볼 수 있다.
- 시스템의 20% 모듈들이 전 자원의 80%를 소비한다.
- 시스템의 20% 모듈들이 실행시간의 80%를 소비한다.
- 오류의 20%가 오류 수정 비용의 80%를 차지한다.
- 도구(tool)의 20% 기능이 사용의 80%를 차지한다.
연습문제
1 1999년 발생한 화성 극지 착륙선(Polar lander)의 실패 원인에 대해 알아보시오.
소프트웨어 오류가 가장 유력한 원인으로 밝혀졌습니다. 탐사선의 소프트웨어는 착륙 과정에서 지표면의 충격을 감지하여 하강 엔진을 끄도록 설계되어 있었습니다. 그러나, 착륙선의 다리가 전개되면서 발생한 진동을 지표면의 충격과 착각하여, 탐사선의 소프트웨어가 하강 엔진을 꺼버린 것으로 추정됩니다.
이외에도, 착륙선의 낙하산이 예상보다 일찍 펼쳐지는 바람에 착륙 속도가 빨라졌다는 설과, 화성 지표면의 예상보다 딱딱한 지질 구조 때문에 착륙 충격이 예상보다 컸다는 설도 제기되었습니다.
SW오류의 구체적인 원인은 다음과 같이 추정됩니다.
- 소프트웨어 개발 과정에서 진동과 충격의 구분에 대한 충분한 검증이 이루어지지 않았습니다.
- 소프트웨어에 대한 테스트가 충분히 이루어지지 않았습니다.
- 소프트웨어의 설계가 복잡하고 비효율적이었기 때문에 오류가 발생하기 쉬웠습니다.
2 다음은 약간 과장된 추석 고향 여행 중에 일어난 에피소드이다. 이 글을 읽고 에러, 결함, 오작동에 대해 설명하시오.
"철수는 추석에 가족과 함께 고향인 부산에 내려가려고 자가용을 운전하였다. 경부 고속도로를 따라 운전하다가 깜빡 졸아 호남 고속도로로 들어가게 되었다. 계속 운전하여 결국에는 광주까지 오게 되었다."
철수의 졸음운전은 오류라고 할 수 있습니다. 오류는 인간의 실수로 인해 발생하는 것으로 철수는 졸음으로 인해 주의력이 산만해져 오류를 범했습니다. 이 오류로 인해 결함이 발생했습니다. 결함은 오류가 시스템에 영향을 미쳐서 발생하는 것(결함은 시스템이 요구사항을 충족하지 못하는 것을 말합니다.)으로 철수의 경우 졸음운전으로 인해 경부 고속도로에서 호남 고속도로로 잘못 들어갔기 때문에 결함이 발생했습니다. 이 결함으로 인해 철수는 오작동을 일으켰습니다. 오작동은 결함으로 인해 발생하는 것으로, 철수의 경우 호남 고속도로로 잘못 들어갔기 때문에 부산으로 가는 길을 잃어버렸습니다.
이 에피소드는 졸음운전의 위험성을 보여주는 좋은 예입니다. 졸음운전은 오류를 유발할 수 있고, 오류로 인해 결함이 발생할 수 있으며, 결함으로 인해 오작동이 발생할 수 있습니다. 따라서 졸음운전을 하지 않도록 주의해야 합니다.
3 소프트웨어 오류의 원인에 대해 아는 대로 기술하시오.
소프트웨어 오류의 원인은 크게 인간적인 요인과 기술적인 요인으로 나눌 수 있습니다.
- 인간적인 요인은 소프트웨어를 개발하고 사용하는 과정에서 발생하는 인간의 실수나 오해로 인해 발생하는 오류
• 설계 오류 : 소프트웨어의 설계 단계에서 발생하는 오류로, 소프트웨어의 기능이나 구조에 결함이 있는 경우
• 구현 오류 : 소프트웨어의 구현 단계에서 발생하는 오류로, 코드에 오류가 있는 경우
• 사용 오류 : 소프트웨어를 사용하는 과정에서 발생하는 오류로, 사용자의 잘못된 조작이나 이해 부족으로 인해 발생하는 경우
- 기술적인 요인은 소프트웨어를 개발하고 사용하는 데 사용되는 기술이나 환경의 한계로 인해 발생하는 오류
• 하드웨어 오류 : 소프트웨어가 실행되는 하드웨어의 결함으로 인해 발생하는 오류
• 운영체제 오류 : 소프트웨어가 실행되는 운영체제의 결함으로 인해 발생하는 오류
• 라이브러리 오류 : 소프트웨어가 사용하는 라이브러리의 결함으로 인해 발생하는 오류
소프트웨어 오류는 다양한 원인으로 인해 발생할 수 있기 때문에 이를 완전히 예방하는 것은 불가능합니다. 하지만, 소프트웨어 개발 및 테스트 프로세스를 철저히 수행하고 소프트웨어를 사용하는 환경을 잘 관리함으로써 오류 발생 가능성을 줄일 수 있습니다.
- 소프트웨어 오류를 줄이기 위한 방법
• 사전 예방 : 소프트웨어 개발 프로세스에서 설계 검증, 코드 검토, 테스트 등을 철저히 수행하여 오류 발생 가능성을 줄입니다.
• 사후 대응 : 오류가 발생하더라도 신속하게 원인을 파악하고 수정하여 피해를 최소화합니다.
소프트웨어 오류는 소프트웨어 개발의 가장 큰 난제 중 하나입니다. 따라서, 소프트웨어 개발자와 사용자 모두 소프트웨어 오류에 대한 이해와 대응 능력을 갖추는 것이 중요합니다.
4 다음 요구사항들은 무엇이 잘못되었는가? 잘못된 점을 지적하고 올바르게 수정하시오.
“이 성적 프로그램은 성적 점수대로 정렬하여야 한다"
“이 시스템은 사용하기 쉬워야 한다"
첫 번째 요구사항
잘못된 점 : 정렬 기준이 명확하지 않다.
정렬 순서가 명확하지 않다.
올바른 수정 : 이 성적 프로그램은 다음과 같은 기준으로 정렬하여야 한다.
* 정렬 기준 : 성적 점수
* 정렬 순서 : 오름차순
두 번째 요구사항
잘못된 점 : 사용하기 쉬움의 기준이 명확하지 않다.
올바른 수정 : 사용자의 요구사항을 명확하게 이해하고 이를 충족할 수 있어야 한다.
* 사용자의 조작이 쉽고 직관적이어야 한다.
* 사용자의 피드백을 수용하고 이를 개선할 수 있어야 한다.
첫 번째 요구사항은 정렬 기준과 순서가 명확하지 않습니다. 따라서, 정렬 기준과 순서를 명확하게 명시해야 합니다.
두 번째 요구사항은 사용하기 쉬움의 기준이 명확하지 않습니다. 따라서, 사용하기 쉬움의 기준을 명확하게 제시해야 합니다.
요구사항을 작성할 때는 다음과 같은 사항을 고려해야 합니다.
- 요구사항은 명확하고 이해하기 쉽도록 작성해야 한다.
- 요구사항은 완전하고 일관되게 작성해야 한다.
- 요구사항은 측정 가능하고 검증 가능해야 한다.
- 요구사항을 잘 작성하면 소프트웨어 개발의 성공 가능성을 높일 수 있습니다.
5 오류를 늦게 발견할 경우 수정 비용이 기하급수적으로 많아지는 이유에 대해 기술하시오.
- 오류의 영향 범위가 커진다. → 많은 부분을 수정해야 함
- 오류의 원인을 파악하기 어렵다 → 많은 시간과 노력을 투자해야 함
- 오류로 인한 피해가 커진다. → 많은 비용을 투자해야 함
예를 들어, 소프트웨어의 설계 단계에서 오류가 발생한 경우 설계 단계에서 바로 수정하면 비교적 간단하게 수정할 수 있습니다. 그러나, 오류가 발견된 시점이 구현 단계나 테스트 단계일 경우 설계 변경이 필요할 수도 있습니다. 설계 변경이 필요한 경우 설계 변경에 따른 테스트와 검증을 다시 수행해야 하므로 수정 비용이 크게 증가하게 됩니다.
오류를 늦게 발견하지 않기 위해서는 다음과 같은 사항에 유의해야 합니다.
- 철저한 요구사항 분석과 설계 검증을 수행한다.
- 잦은 코드 검토와 테스트를 수행한다.
- 사용자 피드백을 적극적으로 수렴한다.
오류는 소프트웨어 개발 과정에서 필연적으로 발생할 수 있습니다. 그러나, 오류를 늦게 발견하지 않도록 노력함으로써 오류로 인한 피해를 최소화할 수 있습니다.
6 완벽한 테스트란 무엇이며 완벽한 테스트가 불가능한 이유를 기술하시오.
- 완벽한 테스트란 소프트웨어가 모든 입력 조건에 대해 올바른 출력을 생성하는지 확인하는 것을 의미합니다. 즉, 소프트웨어가 모든 입력 조건에 대해 오류 없이 동작하는 것을 의미합니다.
- 완벽한 테스트가 불가능한 이유는 다음과 같습니다.
• 입력 조건의 무한대 : 소프트웨어는 무한한 입력 조건을 처리할 수 있습니다. 따라서, 모든 입력 조건에 대해 테스트를
수행하는 것은 불가능합니다.
• 테스트의 비용과 시간 : 모든 입력 조건에 대해 테스트를 수행하려면 많은 비용과 시간이 소요됩니다.
• 테스트의 한계 : 테스트는 소프트웨어의 모든 오류를 발견할 수 없습니다. 소프트웨어의 내부 구조나 동작 방식에 대한 이해가
부족한 경우, 테스트를 통해 발견할 수 없는 오류가 존재할 수 있습니다.
따라서, 완벽한 테스트는 불가능하지만 가능한 한 많은 입력 조건에 대한 테스트를 수행하여 오류를 발견할 가능성을 높일 수 있습니다.
• 입력 조건의 범위 확대 : 모든 입력 조건을 테스트하는 것은 불가능하지만, 가능한 한 많은 입력 조건에 대한 테스트 수행
• 테스트의 자동화 : 테스트를 자동화하여 비용과 시간을 절감
• 테스트의 다양화 : 다양한 방법으로 테스트를 수행하여 오류를 발견할 가능성을 높입니다.
완벽한 테스트는 불가능하지만 철저한 테스트를 통해 오류 발생 가능성을 줄이고 소프트웨어의 품질을 향상시킬 수 있습니다.
7 Pareto 원칙과 소프트웨어 테스트와의 관계에 대해 기술하시오.
Pareto 원칙은 20세기 초 이탈리아의 경제학자 Vilfredo Pareto가 발견한 원칙으로, 전체의 80%는 소수의 20%에 의해 결정된다는 것을 의미합니다.
- Pareto 원칙은 소프트웨어 테스트에도 적용될 수 있습니다. 소프트웨어의 오류 중에서 가장 중요한 오류는 소수의 오류에 집중되어 있다는 것입니다. 따라서, 이러한 중요한 오류를 집중적으로 테스트하여 오류 발견의 효율성을 높일 수 있습니다.
- Pareto 원칙을 적용한 소프트웨어 테스트 방법은 다음과 같습니다.
• 오류의 중요도 분석 : 소프트웨어의 모든 오류를 중요도에 따라 분류
• 중요 오류에 대한 집중 테스트 : 중요 오류에 대한 테스트를 집중적으로 수행
- Pareto 원칙을 적용한 소프트웨어 테스트를 통해 다음과 같은 효과를 얻을 수 있습니다.
• 오류 발견의 효율성 향상 : 중요한 오류를 집중적으로 테스트하여 오류 발견의 효율성을 높일 수 있습니다.
• 테스트 비용 및 시간 절감 : 중요한 오류에 대한 테스트만 수행하므로, 테스트 비용 및 시간을 절감할 수 있습니다.
8 소프트웨어 테스트 원칙에 대해 기술하시오.
소프트웨어 테스트 원칙은 소프트웨어 테스트를 수행하는 데 있어 지침이 되는 원칙입니다. 소프트웨어 테스트 원칙은 다음과 같은 것들이 있습니다.
- 테스트는 결함이 존재함을 밝히는 활동이다.
• 테스트는 소프트웨어에 결함이 있는지 여부를 확인하는 활동으로 테스트를 통해 소프트웨어가 결함이 없다고 증명할 수는
없습니다.
- 완벽한 테스트는 불가능하다.
• 모든 입력 조건에 대해 테스트를 수행하는 것은 불가능합니다.
- 테스트는 개발 초기 단계부터 시작해야 한다.
• 테스트는 소프트웨어 개발 초기 단계부터 시작해야 합니다. 소프트웨어 개발 초기 단계에서 오류를 발견하면, 수정 비용이
적게 들고 개발 일정에 미치는 영향이 적습니다.
- 결함은 어디에나 존재한다.
• 결함은 소프트웨어의 모든 단계에서 발생할 수 있습니다. 소프트웨어 개발 및 테스트 프로세스 전반에 걸쳐 결함을 발견하기
위한 노력을 기울여야 합니다.
- 테스트는 정황에 따라 이루어져야 한다.
• 소프트웨어는 다양한 환경에서 사용될 수 있습니다. 소프트웨어가 사용될 환경을 고려하여 테스트를 수행해야 합니다.
- 오류-부재의 귀변은 없다.
• 오류가 발견되지 않았다는 것은 오류가 없다는 것을 의미하지 않습니다. 오류가 발견되지 않았다고 하더라도
소프트웨어에 결함이 존재할 수 있습니다.
소프트웨어 테스트 원칙은 소프트웨어 테스트의 효율성과 효과를 높이기 위해 지켜야 할 중요한 원칙입니다.
|