S/W Testing - ① 에서 S/W Testing(Verification & Validation)과 Verification의 2가지 방식(static & dynamic)에 대해 다뤘다. Inspection 과 Testing을 통해 S/W Verification을 수행한다는 것을 확인하였다.
① Planning
② Overview
③ Individual preparation
④ Inspection meeting : 팀단위로 모여 inspection 수행 (QA)
⑤ Rework : insepection 산출물을 토대로 수정 (개발자)
⑥ Follow up
※ 개발자는 Inspection을 수행하지 않는가?
: 절대 아니다. 개발자는 기본적으로 본인이 작성한 코드에 대해 individually inspection을 수행하여야함.
: language dependant, language에서 자주 발생하는 에러의 리스트
※ Types of checking
- strong : 함수, 변수의 타입을 철저히 지키도록 (에러 발생)
- weak : checklist의 양이 많아짐
Data faults
a. 변수 초기화 여부
b. 배열이 선언된 영역 바깥을 접근하지 않는가
c char 배열 선언 시 null 자리를 생각했는가
d buffer overflow 발생 여지
Control faults
a. 무한루프 발생 가능성
b. break가 적절히 삽입되었는가
c. {} 중괄호흫 제대로 작성하였는가
Input/output faults
a. 모든 입력 변수가 사용되었는가
b. 모든 출력 변수가 출력 전 초기화 되었는가
c. 정해진 입력 외의 값 입력시 비정상 종료되지 않는가
Interface faults
a. 모든 함수와 메서드의 매개변수의 순서와 타입이 제대로 되었는가
b. 다쓴 메모리는 반환하였는가
Exception management faults
a. 모든 error condition을 고려하였는가
즉 tools이 유용한 supplement지만 replacement of inspection은 아니다.
(saving effort & time forrr developer)
※ chatGPT는 생산성을 높여주는 Tool일 뿐, 개발자는 chatGPT가 제공하는 정보를 판단할 수 있는 지식과 경험이 있을 때 효과적으로 사용할 수 있음
(모든 Tool이 마찮가지)
특히 c처럼 weak type checking language에 유용(<> java)
(Java는 코드 작성 시 오류가 뜨는 반면 C는 허용하는 경우를 잡아낼 수 있음)
If S/W does not satisfy 'what it is intended to do' -> defect
testing의 본질은 에러가 없다를 증명하는게 아니라 에러가 있음을 찾아내는 것
Exhaustive Testing을 통해 모든 에러를 없앨 수 는 없을까? -> 비현실적, 불가능
< Exhaustive Testing >
: 모든 걸 다 커버하는 테스팅
=> testing은 한계가 있다. (모든 경우의 수를 다 테스트해볼 수 없다)
=> inspection이 필수
but, only verification method for non-functional (usability, security, performance 등)
※ 참고로, 버그 리포트 중 재현이 안되는 error는 에러의 위치를 찾는 것이 어려워짐
=> 경험이 많을 수록 유리(사실 코딩보다 어려운 일임)
Reinspection & Re-testing
=> Regression testing
: 바꾼 코드에서 웬만하면 또다른 문제가 생김 (new problem derived from change)
① component(group of class) testing : 대략 한 개발자가 개발할 수 있는 단위
- 본인(개발자)이 Inspection & Testing
- by developer
② system testing : integrated component , compoent를 통합하는 과정에서 수행하는 testing
- by independent team
=> reporting
=> regression
※ 결론은, Verification을 위해 정적인 검증(inspection)과 동적인 검증(testing)이 모두 필요하다. Critical한 S/W일수록 Inspection의 비중이 크다. 그러나 Testing은 non-functional을 검증할 수 있는 유일한 방법이므로 결국 둘다 필요하다.
component간 interaction testing
incremental testing
이때 interaction testing은 인터페이스를 테스팅한다고 보면 됨(interface interaction)
incremnetal testing to locates error eaasily
실제 customer한테 배포되기 전의 Testing 이므로 실제 user와 같은 시나리오로 테스팅
따라서 input과 output만을 확인
내부 시나리오(구조)는 고려하지 않으며 테스터가 S/W와 관련된 지식이 없으며, 오직 Requirements Spec을 토대로 평가한다고 가정
(반면 Integration testing은 인터페이스의 구조를 알고 이를 바탕으로 테스팅을 수행)
테스트 시나리오(테스트 케이스)는 Requirements Specification 이후에 작성. (즉 design 이전에 작성된 테케이므로 내부 구조는 신경쓰지 않음)
테케는 에러가 발생할 법한 경우를 고려해서 작성
exhaustive testing이 불가하므로 최소한의 테스트케이스로 최대한 많은 것을 커버할 수 있도록 설계하는 것이 중요! (equivalence partition)
예를 들어, if(a>=0) else 구문이 존재한다.
두 가지 값만 테스트 해볼 수 있다면?
※ 각 파티션을 대표하는 값을 하나씩 테스트해보는것. 즉 파티션별 테케를 하나씩 작성할 것
또다른 예를 확인해보자.
e.g 로그인 기능 개발하였다. 어떤 테스트 케이스를 고려해야하는가?
ⓐ input: valid(ID,PW already exists)
ⓑ invalid input(ID가 없는 경우)
ⓒ invalid input (ID는 있는데 pw가 달라)
ⓓ invalid input(둘 다 입력하지 않는 경우)
ⓔ invalid input(둘 다 틀린 경우)
ⓕ ID 허용 최소 길이 & 최대 길이 각각에 대해