...
소프트웨어 품질
소프트웨어의 유용성을 얻기위해 갖춰야하는 특성들의 집합, 사용자의 요구사항이나 만족도를 얼마나 충족시키는가의 지표
+ 프로젝트 초기에 결함을 발견하지 못하고 개발 이후에 발견 시 많은 수정 비용이 발생 됨.
+ 품질 문제 -> 경쟁사에게 이득이됨. 자사의 이미지 하락.
소프트웨어 테스트이란?
- 프로그램에 존재하는 오류 와 결함을 검출하여 수정하고 요구사항에 부합되는지를 확인하며 소프트웨어의 품질을 향상시키는 것을 목적.
- 에러를 발견 할 목적으로 프로그램을 실행하는 프로세스
- 버그 발견을 목적으로 소프트웨어를 분석 또는 운영하는 프로세스
- SW가 정해진 요구를 만족하는지, 예상과 실제 결과가 어떤 차이를 보이는지 수동 또는 자동화된 방법을 동원하여 검사하고 평가하는 일련의 과정을 의미
- 최종적으로는 결함 데이터를 근간으로 개발 프로젝트의 리스크에 대한 수치적인 판단 근거를 의사 결정자에게 전달
왜 소프트웨어 테스트가 중요한가?
- 목적 : 단순히 작동여부를 확인하는것이 아니라, defect발견하려고 프로그램을 실행. 명세 충족 확인, 고객 요구 충족 확인, 결함 발견
- sw test는 단순 오류 제거가 아닌 회사 가치를 판단하는 기준이 되기 때문에.
- 테스트 유형별 목적
인수 테스트 : 예상대로 시스템이 동작하는지 확인하고 요구사항에 맞는지 확신을 얻는 것.
유지 보수 테스트 : 개발과정에서 변경작업이 일어나는 경우 새로운 결함이 유입되지 않았는지 확인하는 것
운영 테스트 : 실제 운영 환경에서 신뢰성 또는 가용성 등 시스템의 특성을 평가하는 것.
소프트웨어 테스트 원리
[1] Testing shows presence of defects
테스팅은 결함이 존재함을 밝히는 활동이다. 결함이 존재함을 밝히지만 결함이 없다는 것을 증명할 수는 없다.
[2] Exhaustive testing is impossible
완벽한 테스팅은 불가능하다. 따라서 리스크 분석과 결정된 우선순위에 따른 테스팅(Risk-based testing) 필요하다
[3] Early testing
테스팅을 개발 초기에 시작함으로써 결함 예방 및 조기 발견을 통해 높은 수준의 품질확보 및 개발 기간을 단축시키는 효과를 기대할 수 있다.
[4] Defect clustering
복잡한 구조를 가지고 있거나 다른 부분과 복잡한 상호 작용이 많은 모듈 또는 개발 난이도가 높고 최신 기술을 사용하여 새롭게 개발된 모듈, 경험이 미흡한 개발팀에서 개발한 적은 수의 모듈에서 대다수의 결함이 발견되고 운영상에 장애를 초래한다. (결함 집중현상)
[5] Pesticide Paradox
동일한 테스트 케이스로 동일한 테스트를 반복적으로 수행하면 새로운 결함을 찾아내기 어려움, 따라서 보다 많은 결함을 발견하기 위해서는 테스트케이스를 지속적으로 보완, 개선할 필요가 있고 다른 시각/기법으로 테스트하는 것이 필요하다.
[6] Testing is context dependent
테스팅은 Context에 따라 다르게 진행된다. 예를 들어 안전이 최우선 되는 소프트웨어 테스트와 전자 상거래 사이트 테스트는 다르게 진행해야 한다.
[7] Absence-of-errors fallacy
많은 결함을 수정하는 것이 사용자/고객의 만족을 보장하지 않는다. (오류-부재의 궤변) 품질이 보증된 제품도 시장에서 실패하는 경우가 있음
SW개발 생명주기상에서의 테스트
Waterfall Model (폭포수 모델)
- 폭포 흐름 같이 순차적으로 진행
- 실제 개발 환경에는 맞지 않음
- 폭포수 모델의 문제점을 보완한 변형된 폭포수 모델들 등장
테스트 단계에서 문제점이 발견되면 요구사항 분석 단계부터 다시 전체 개발 프로세스를 진행해야 함.
변형된 폭포수 모델에서는 필요에 따라 이전의 임의의 단계에서부터 개발 프로세스를 진행 할 수 있도록 함.
V Model (폭포수 모델)
소프트웨어 검증 (Verification)
최종 산출물이 아닌 중간 단계 산출물(work product)이 정의된 요구사항을 만족하는지 평가하는 과정.
+ 소프트웨어 제품을 제대로 만들어 가고있는지?
+ 계획서, 요구사항정의서, 설계 문서, 프로그램 코드, 테스트케이스
소프트웨어 검사 (Validation)
개발 과정의 최종 단계에서 개발된 소프트웨어 제품이 비즈니스 요구사항을 만족하는지 평가하는 과정.
+ 제대로 된 (사용자 요구사항을 만족하는) 소프트웨어 제품을 만들었는지?
+ 소프트웨어 제품
단계별 테스트
- 단위 테스트 : 소스를 대상으로 테스트
- 통합 테스트 : 단위 간 상호 연동 통합 테스트
- 시스템 테스트 : 사양과 코딩 이외에 정해지지 않은 변칙적인 행위까지 포함해 테스트. (성능, 사용성, 신뢰성, 효율성, 유지보수성, 이식성)
(가볍게는 로그인화면에 생성되지 않은 ID나 잘못된 비밀번호를 입력했을 때, 에러창과 메시지가 제대로 출력되고 다시 재입력이나 다른 행동이 요구사양대로 만들어졌는가 확인하는 작업이 대표적)
- 인수 테스트 : 런칭 후 베타테스트 격. 결함 찾기가 아닌 사용자 만족 여부를 테스트. 사용자가 인수할만한 수준인지 판정하기 위한 테스트.
- 운영 테스트 : 신뢰성 또는 가용성 같은 시스템의 특성을 평가하는 것.
테스트 수명주기와 프로세스
테스트 케이스 설계 기법
- 테스트 기획서 : 모든 요구사항을 내포하고 있는 문서. TC는 이 문서를 기준으로 한다.
- 테스트 시나리오 : 테스트 될수 있는 기능, 테스트가 필요한 상황, conditon값
- 테스트 케이스 : 테스트를 수행하기 위한 데이터 집합
시나리오를 문서화.
- 테스트 절차서 : 테스트 케이스의 실행 순서 절차
소프트웨어 테스트 분류
1. 소프트웨어 개발 단계에 따라
2. 프로그램 실행여부에 따라
3. 테스트 케이스 설계 방법에 따라
4. 입력 값의 유효성 여부에 따라
5. 스크립트 유무에 따라
6. 테스트 목적에 따라
- 동적테스트 -
동적테스트는 말 그대로 움직여서 테스트해본다. 즉 테스트 대상물을 직접 다루어서 테스트 해보는 것입니다.
게임잡에서 구인을 볼때 이 방식이 게임에서는 가장 많이 쓰이는 방식이라 생각 됩니다. 정해진 내용을 확인하고 기록하는 방식이니, 크게 어렵지 않지만, 시간과의 싸움이고 테스터가 그만큼 꼼꼼해야 한다는 단점이 있습니다. 예로는 버튼 눌러본다던지, 강화를 해보거나 플레이를 해보는 방식 등이 해당됩니다.
- 정적테스트 -
프로그램을 실행하지 않고 툴을 이용해서, 프로그램 작성시 구문에 표현방법 문법 규칙에서 벗어난 오류를 찾거나 잠재적인 코드 오류 개선
- 스크립티드 테스트 -
스크립트가 만들어져있고 그대로 따라가는 테스트입니다. 자동화 공장에서 많이 쓰죠. 망가지면 정지버튼 누르는 확인자라던지, 아이스크림에 불량나오면 건져내기라던지...
- 탐색적 테스트 -
경험과 직관에 의존하여 테스트케이스를 작성하여 테스트를 수행한다고 합니다.
로또 번호 찍듯이 찍는 게 아니라 많은 경험으로 특정부분의 에러가 짙은 경우 또 에러가 날 가능성이 높으므로 그쪽 비중을 늘린다던지 그런 것입니다.
- 리그레션 / 회귀 테스트 -
처음에 하드코딩으로 작성된 것에 에러가 발견되어서 보고를 하면 다시 수정해서 보내줍니다. 보고 다시 사양서대로 되었는가 확인하는 작업을 거칩니다. 수정 확인 절차는 매우 중요하니까요. 일반적으로 시스템 테스트 단계부터 시작합니다.
그리고 하나 꼭 알아두어야 할 것은 수정전 것들도 다시 체크해볼 필요가 있습니다. 코드가 변경되어서 전에는 잘 작동하던 것이 지금은 작동안할 수 있으니까, QA는 반복적인 작업이 많습니다. 그만큼 챙겨야하는 것도 많고, 역시나 테스트 케이스나 테스트 계획이 좋으면 효율이 좋겠지요.
- 스모크 테스트 -
빌드가 테스트 할만한 수준인지 확인하는 테스트입니다. 중요한 부분만 먼저 확인을 하여, 전반적인 테스트를 할 필요가 있는지 없는지 확인하는 테스트입니다. 아직 제대로 구동하고 있지 않은데 테스트를 할 필요는 없으니까요.
- 침입 테스트 :
보완테스트입니다.
- 성능 테스트 :
서버의 응답시간이나 리소스를 잘 활용해서 처리하고 있는가 확인해보는 테스트입니다.
- 신뢰성 테스트 :
게임에서 정기적으로 점검시간을 가지는 게임들이 많습니다. 동작 후 실제 테스트에는 문제가 없더라도, 메모리 릭이나 테스트상에서 단발로 드러나지 않는 문제점 또한 존재합니다. 온라인 게임같이 24시간 꾸준하게 서비스 하는 건 점검없이 계속 유지되면 좋지만, 그러지 못할 경우 몇일 몇 시간까지 보장되는게 중요합니다. 그런 여부를 테스트 하는 거라고 합니다.
소프트웨어 오류
소프트 웨어 오류의 원인
소프트웨어 오류의 원인으로는 요구 사항 오류, 설계 오류, 코딩 오류, 기타 오류가 있습니다.
1) 요구사항의 오류 - 56%
- 고객은 왕이지만, 모든 왕들이 현명하고 총명하고 항상 바른 역사만 있었던 것이 아니듯이, 잘못된 요구 사항을 정의하거나, 저같이 전달력 부족으로 제대로 의사가 전달되지 못해 오류가 발생할 수도 있습니다.
ex) 랭킹 점수판은 점수순으로 정렬해야 합니다 ( x ) → 랭킹 점수판은 '오름차 or 내림차' 점수순으로 정렬해야합니다.
- 전부다 고객이 잘 못해서 이런거다 라고 몰기에는 시간이나 예산 문제로 개발자가 의도적으로 빼먹는 일도 있습니다. 일부러 구현을 안하는 것이죠.
- 그리고 고객이 나중에 추가 요청하는 경우도 있습니다. 항상 시간이 지나면 더 좋은 생각이 떠오르는 건 누구든 예외가 없습니다.
- 마지막으로 개발자가 이건 내가 봐도 기가막히다 하면서 요구 사항에 없는 기능을 추가하는 경우도 있습니다. (눈물을 머금고 삭제하고 요구사항대로 돌아가겠지만 말입니다. 나무 아멘)
2) 설계 오류 - 27%
- 저번에 말씀드렸듯이 V모델에 따라보면 요구사항이 나오면 분석 및 설계의 단계를 거칩니다. 요구사항을 설계하는 과정에서 오류가 발생하기도 합니다. 위의 내용과 어느 정도 겹쳐지는 부분입니다.
3) 코딩 오류 - 10%
- 설계 문서를 제대로 이해 못 하였거나, 잘못 해석하는 경우, 프로그래밍 언어 또는 개발도구가 익숙치 않아 발생하는 오류가 여기에 해당됩니다.
4) 기타 오류 - 7%
- 문서나 코딩표준을 따르지 않는 경우와 미흡한 테스트 프로세스가 여기에 해당됩니다. 모바일 개발을 하시는 분들은 OS 버젼이 올라가면서 호환성에 고통받고 계실텐데요. 아직은 지원하는 거라도 나중 버젼업되면 사라지는 기능이 있다던지 대체되는 코드등에 대한 대처를 하지 못해서 생기는 오류가 있고, 테스트 프로세스가 제대로 받쳐주지 못하면 잠재적 오류를 발견하지 못해 문제가 생기는 경우도 있을겁니다.
소프트웨어 오류의 밀집성
- 인간이 하는 일이다보니 소프트웨어가 자주 오류나는 부분은 오류나는 수만큼 오류 존재 가능성이 비례하게 존재합니다.
테스터의 한계
- 완벽한 테스트는 불가능하고 무한한 테스트는 비현실적입니다. 시간과 돈은 한정적이기 때문입니다.
지금 제가 적고 있는 이 블로그도 이용자에게는 간단한 것이지만, 제가 쓰고 있는 이 게시판 조차 '폰트수 x 폰트 사이즈 x 입력창수 x 버튼 수 x 모든 문자의 경우의 수'만큼의 경우의 수가 존재합니다. 이미 키보드에서 표현가능한 모든 문자의 수가 들어온 시점에 불가능함이 보이지 않으십니까? '섻곇쵟곣 콗낛믻'로 입력하면 오버플로우가 일어나 게임이 종료되는 채팅창을 게임에 도입했다고 할 때, 유저는 이걸 찾아낼 수 있을지도 모르지만, 테스터는 이걸 발견하기는 어려울 것입니다. 저기까지 도달할 수 있는 경우의 수는 무한대에 근접해있기 때문입니다. 그래서 테스트 기준이라는 게 필요로 합니다.
테스트 기준
- 간단하게 테스트를 얼마나 어떻게 진행할지 전체 영역중에 얼마나 만족하면 합격이라고 할지, 테스트 종료는 언제할지를 정하는 것입니다.
이건 개인 역량이 매우 중요한 거라, 이거다! 라고 말씀드리긴 어렵네요. 제 기준이라면 나중에 이야기 할 내용이지만, 100% 분기커버리지만 만족한다면 되지 않을까 싶습니다. MMORPG에서는 적용하기 힘든 것이지만 모바일은 경우의 수와 실제 게임사이즈가 크지 않기 때문에 가능하다고 생각합니다.
테스트 용이성 종류
제어용이성(controllability)
프로그램을 제어하기 용이하도록 성계
관찰가능성(obserbility)
프로그램 내부 상태를 쉽게 파악할 수 있도록 설계
단순성(simplicity)
시스템 구조가 단순할수록 효율적인 테스트 가능
분할용이성(operability)
테스트할 대상 영역을 제어하여 문제가 발생된 곳으로 고립시킴으로써 독립적으로 모듈을 테스트 할 수 있도록 설계
운영 용이성(operability)
프로그램이 오작동 하여도 테스트 작업을 계속 할 수 있도록 설계
안정성(stability)
테스트동안에 소프트웨어 변경이 자주 발생되지 않도록 설계
이해용이성(understandability)
소프트웨어 설계정보가 잘 조직화 되어 쉽게 접근 가능하도록 하여 소프트웨어를 더욱 잘 이해할 수있도록 설계
에러, 결함 고리고 오작동
이게 에러인지 결함인지 오작동인지 경계선이 애매합니다. 이건 한번 짚고 넘어가는 것도 좋을 듯합니다.
- 에러(human error) : 영어에서 보이듯 인간의 실수를 에러라고 정의합니다.
- 결함(fault) : 인간이 실수를 했으니 결함으로 나타나는 것은 당연합니다. 누락하는 경우와 오입력의 경우가 그런 경우일 것입니다.
- 오작동(failure) : 실수 했으니 결함이 나오고, 오작동을 하는 것은 당연합니다. 하지만, 오작동이라고 하여 결과값이 반드시 거짓인 것은 아닙니다. 예로 들면, 제가 일전에 만들었던 상인에게 접근하면 UI가 열리는 영상을 보여드렸습니다.
void OnTriggerEnter(Collider col) {
if (col.gameObject.CompareTag("Player")) {
gameObject.GetComponent<Renderer>().material.color = Color.blue;
sellerStat = SellerStat.sayHi; ui.SetActive(true);
}
}
if 문이 있어 플레이어의 경우만 반응하도록 되어 있습니다. 하지만,
void OnTriggerEnter(Collider col) {
gameObject.GetComponent<Renderer>().material.color = Color.blue;
sellerStat = SellerStat.sayHi; ui.SetActive(true);
}
이렇게 짠다고 한들 플레이어가 들어갔을 때 UI창이 열리는 건 동일합니다.
다른 오브젝트가 들어가도 UI창이 열리는 오작동이 발생하지만, 실제 테스트에서는 정상작동으로 인식할 것입니다.
다른 변수가 들어가면 시도 때도 없이 UI가 열려 있겠지만 말입니다.
소프트웨어 테스트 7원칙
1. 테스트는 반드시 프로그램을 개발한 팀이나 프로그래머와는 무관한 그룹에 의해서 수행되어야 한다.
→ 크리에이터는 자신의 작품에 대해서 사심이 들어가 정확한 테스트가 어려운 경우가 있기 때문입니다.
2. 테스트 작업을 가장 능력이 뛰어난 사람이 하여야 한다
→ 마무리가 좋아야 모든 게 좋다는 말이 있듯이, 마무리를 하는 사람이 유능하긴 해야하는데, 아직은 좀 더 의식이 개선되어야 할 듯 합니다.
3. 오류가 발견되지 않을 것이란 가정하에 테스트 계획을 수립하지 마라.
→ 테스트는 오류를 발견하는데 의의가 있는 작업이죠.
4. 타당하지 않고 예상치 못한 경우에 대해서도 테스트를 수행하라
→ 실제 사용하는 고객들은 제품에 대해서 이해도 높지 않은 상황에서 알아가는 작업을 거칩니다. 그 사이에 제작사들이 많은 예측하지 못한 일들이 벌어지죠. 그런 부분까지 전부는 아니더라도 상당부분은 예측해서 테스트할 필요가 있다는 것입니다.
5. 오류가 남아있을 확률은 이미 발견된 오류의 수에 비례한다
→ 오류가 있었던 부분이 수정되었다고 한들, 자주 발생한 곳에는 다시 오류가 생길 가능성이 높다는 이야기입니다. QA입장에서는 중점적으로 확인할 필요가 있겠습니다.
6. 테스트케이스를 체계적으로 관리하라.
→ 효율이 높아지고, 업무도 줄어들 것입니다. (프로젝트가 커지면 커질수록 쉽진 않습니다.)
7. 각각의 테스트 결과를 철저하게 점검하라
→ 지속적으로 관리를 하라는 의미입니다.
이 글이 좋으셨다면 구독 & 좋아요
여러분의 구독과 좋아요는
저자에게 큰 힘이 됩니다.