Software Testing
소프트웨어 테스팅
- 넓은 의미로, Verification과 Validation을 이행하는 과정을 일컫는다.
- Verification (검증)
"Are We Building the Product Right?"
- 소프트웨어가 Specification에 맞게 동작하는가를 확인한다.
- Valiadtion (유효성 확인)
"Are We Building the Right Product"
- 소프트웨어가 사용자의 Requirements를 충족하는가를 확인한다.
- Verification과 Validation은 서로 상호 보완적이며,
소프트웨어가 목적에 맞게 만들어졌는지에 대한 Confidence를 얻는데 목적을 두며,
Defect(Bug)가 완전히 제거된 소프트웨어를 의미하지는 않으며,
사용하려는 용도에 맞는 소프트웨어임을 확인하는데 의의를 둔다.
- Verification은 확인 대상에 따라 Static Verification. Dynamic Verification으로 나뉘며,
각각이 확인(검증)하는 대상은 아래 그림과 같다:
Inspection (Static Verification)에서 검증하는 대상은 아래와 같다:
- Requirements Specification
- Software Architecture
- UML Design Models
- Database Schemas
- Program (Source Code; High-Level Code)
- System Prototype
Testing (Dynamic Verification)에서 검증하는 대상은 아래와 같다:
- Program (Executable; Binary Code)
- System Prototype
Software Inspection (Static Verification)
- 소프트웨어를 실행하지 않고,
소프트웨어의 Anomaly와 Defect를 찾기 위해 Static System Representation을 분석하는 작업 전반을 의미한다.
(소프트웨어의 Defect를 Detection하는데 목적이 있으며, Correction은 여기에 포함되지 않는다.)
- Document를 Review하는 Formal Approach이다.
- Critical한 Software일수록, Testing보다는 Inspection에 중점을 두고 테스팅한다.
Inspection에서 찾고자 하는 Defect의 종류는 아래와 같다:
- Logical Error
- Anomaly
- Erroneous Condition
- Uninitialized Variable과 같은 문제가 생길 소지가 있는 부분을 의미한다. - Non-Compliance with Standard
- Static System Representation의 종류는 아래와 같다:
- Requirements
- Tool-Based Document
- Design
- Code
- Configuration Data
- Test Data
Inspection을 수행하기 위한 Pre-Condition은 아래와 같다:
- Precise Specification
- References of Syntactically Correct Code
- 구현하는데 사용된 프로그래밍 언어의 정확한 Syntax를 구현하기 위한 Reference
- Error Checklist
- Acceptance of Management
- 초기 Inspection은 큰 Cost가 발생하기에, 경영진의 동의가 필요하다.
- Management should not Use Inspections for Staff Appraisal
- 경영진은 Inspection을 인사 고과에 반영해서는 안된다.
- 발생시킨 Defect를 각각의 Staff의 성과에 반영시킬 경우, Inspection이 소극적으로 이루어지게 된다.
Inspection이 진행되는 과정은 아래와 같다:
- Inspection Team에게 System Overview, Code, 관련 Document를 제공한다.
- Team이 다같이 모여 Inspection을 진행하며 Error를 찾고 기록한다.
- Inspection Team이 Development Team에게 발견한 Error를 전달한다.
- Development Team이 Error를 고친다.
- Inspection Team이 수정된 소프트웨어를 건네받아 Re-Inspection한다.
- Inspection시 필요한, Checklist를 구성하는 내용은 아래와 같다:
- Common Error에 대한 내용
- Initialisation, Constant Naming, Loop Termination, Array Bound 등
- 특정 Programming Language에서 흔히 발생하는 PL-Dependent한 Error
- Weak Type Checking을 수행하는 PL의 경우, 더 많은 Error를 발생시킬 수 있다.
Example. Inspection Checklist
Category | Description |
Data Faults |
- Are all program variables initialised before their values are used? - Should the upper bound of arrays be equal to the size of the array or Size-1? - If character strings are used, is a delimiter explicitly assigned? - Is there any possibility of buffer overflow? |
Control Faults |
- For each conditional statement, is the condition correct? - Is each loop certain to terminate? - Are compound statements correctly bracketed? - In case statement, are all possible cases accounted for? - If a break is required after each case in case statements, has it been included? |
I/O Faults |
- Are all input variables used? - Are all output variables assigned a value before they are output? - Can unexpected inputs cause corruption? |
Interface Faults |
- Do all function and method calls have the correct number of parameters? - Do formal and actual parameter types match? - Are the parameters in the right order? - If components access shared memory, do they have the same model of the shared memory structure? |
Storage Management Faults |
- If a linked structure is modified, have all links been corectly reassigned? - If dynamic storage is used, has space been allocated correctly? - Is space explicitly de-allocated after it is no longer required? |
Exception Management Faults |
- Have all possible error conditions been taken into account? |
- Inspection의 장점은 아래와 같다:
- 한 번의 제대로 된 Inspection으로 많은 Defect(Bug)를 발견할 수 있다.
- Testing에서는 하나의 Defect가 발견되면 Testing이 중단되고 다른 Defect를 찾는 과정이 지연되는 경우가 잦다. - Programming적 지식과 경험이 있다면, 전형적인 에러를 쉽게 찾을 수 있다.
- Inspection의 단점은 아래와 같다:
- Non-Functional Requirement와 Usability를 충족하는지 확인하기 어렵다.
- 이들은 반드시 Testing을 통해 검증해야 한다.
Automation Tool for Static Analysis
- Static Analyser
- Source Text를 Processing하는 도구이다.
- Program Text를 Parsing하여 "Potentially" Erroneous Condition을 찾는다.
- Inspection 전 과정을 대신할수는 없지만, 매우 효율적으로 Inspection을 수행할 수 있게 한다.
- C Language와 같은, Weak Typing Language에서 발생하는 Error를 효과적으로 탐지해낸다.
Example. LINT Analyser
138% more lint_ex.c
#include <stdio.h>
printarray(Anarray)
int Anarray;
{ printf("%d", Anarray); }
main()
{
int Anarray[5]; int i; char c;
printarray(Anarray, i, c);
printarray(Anarray);
}
139% cc lint_ex.c
140% lint lint_ex.c
line_ex.c(10): warning: c may be used before set
line_ex.c(10): warning: i may be used before set
printarray: variable # of args. lint_ex.c(4) :: lint_ex.c(10)
printarray, arg. 1 used inconsistently lint_ex.c(4) :: lint_ex.c(10)
printarray, arg. 1 used inconsistently lint_ex.c(4) :: lint_ex.c(11)
printf returns value which is always ignored
Software Testing (Dynamic Verification)
- Test Data를 통해 소프트웨어를 Execution하면서 Operation이 의도한대로 동작하는가를 확인하는 작업 전반을 의미한다.
- Non-Functional Requirement를 Verification하는 유일한 방법이다.
- Testing은 아래와 같이 구분된다:
- Validation Testing
- 소프트웨어가 사용자의 Requirement를 만족하는지(구현되어있는지)를 확인한다.
- Defect Testing
- Defect을 찾아내기 위한 테스트로, Test Data를 구조적으로 설계하는 것이 매우 중요하다.
- Regression Testing
- Defect를 Corrrection한 이후, 수정된 부분으로 인해 새로운 Defect가 발생하지 않는지를 확인한다.
* Debugging
- Defect(Error)가 발생하는 위치를 찾고, 고치는 작업 전반을 의미하며,
Defect의 존재 여부를 찾아내는 Defect Testing과는 구분된다.
Testing이 진행되는 과정은 아래와 같다:
Testing Process | Description | |
Component Testing (Unit Testing) |
- 개별 Program Component에 대해 수행하는 테스트이다. - 일반적으로 해당 Component 개발자 본인이 수행하며, Critical한 경우, 다같이 Testing하는 경우도 있다. - Testing Quality가 개발자의 숙련도에 의존적이다. |
|
System Testing |
System Testing |
- System이 Specification에 맞게 동작하는지를 테스팅한다. - 테스팅된 Component들을 Integration한 후에 수행하는 테스트이다. - 각각의 Component들의 Interface 테스트에 집중해야 한다. (개별 Component들은 테스팅이 완료된 상태이기 때문이다.) - System Testing은 Integration Testing과 Release Testing으로 구분된다. |
Integration Testing |
- 여러 Component들을 Integration하고 Component 사이의 Interaction에서 발생할 수 있는 문제를 테스팅한다. - Error를 보다 쉽게 Localization하기 위해, Incremental Integration한다. - 독립적인 Testing Team이 수행한다. |
|
Release Testing (Acceptance Testing) (Alpha Testing) |
- 실제 고객들에게 Deploy될 시스템에 수행하는 테스트이다. - Requirement를 기반으로 사용자들이 잘 사용할 수 있을지를 테스트한다. - Black-Box Testing이다. (System의 Specification에만 의존하며, 내부 Implementation Detail은 모르는 상황에서 진행하는 테스트이다.) |
|
Customer Testing (Beta Testing) |
* Incremental Integration Testing
- Integration을 거듭해가면서 처음 Integration된 Component들은 더 많은 테스트를 거치게 된다.
(이때, 이전 테스트에 사용되었던 Test Case는 폐기하지 않고 재사용한다.)
Equivalence Partition (for Partition Testing)
- Testing에 사용될 Test Case를 만들 때 사용되는 Technique이다.
- 동일한 Output Result를 야기하는 Input Data들의 집합인 Equivalence Partition(Class)들로 구성된다.
- Test Case들은 각각의 Partition들로 구성되어야 한다.
Example. Equivalence Partition
- 짝수 홀수를 판별하는 프로그램에서는
홀수값으로만 구성된 Equivalence Partition과 짝수로만 구성된 Equivalence Partition으로 Test Case가 구성될 수 있다.
Example. Equivalence Partition
- 위와 같은 Condition으로 구성된 Logic에서는 Equivalence Partition이 3개로 구성될 수 있다.
- Condition의 경계에서 오류가 발생될 확률이 높으므로, 일반적으로 경계값 위주의 테스팅을 수행한다.
Example. Extraction Process of Equivalence Partition for Search Routine
procedure Search (Key : ELEM;
T : SEQ of ELEM;
Found : in out BOOLEAN;
L : in out ELEM_INDEX);
Pre-condition
-- the sequence has at least one element
T'FIRST <= T'LAST
Post-condition
-- the element is found and is referenced by L
(Found is true and T(L) = Key)
or
-- the element is not in the array
(Found is false and not (exists i, T'FIRST <= i <= T'LAST, T(i) = Key))
- Pre-condition은 Routine을 수행하기 전 만족해야할 조건으로, Input의 Validation을 결정하는 기준이다.
- Post-condition은 Routine을 수행한 후 만족해야할 조건으로,
위 코드에서는 Search에 성공했을 경우의 조건과 실패했을 경우의 조건을 나열하고 있다.
- Input Partition은
Pre-condition을 만족하는 데이터, Pre-condition을 만족하지 않는 데이터,
Key가 T에 속하는 경우, Key가 T에 속하지 않는 경우,
T에 원소가 없는 경우, T의 원소가 하나인 경우, T의 원소가 다수인 경우,
Key가 T의 첫 번째 원소인 경우, Key가 T의 중간에 위치할 경우, Key가 T의 마지막 원소인 경우로 나눌 수 있다.
Example. Testing Phases (in Plan-Driven Software Process)
- 맨 처음, Requirements Specification 과정에서 만드는 Customer Test Plan(= Test Case)을
맨 마지막 Cuttomer Test에서 사용하는 것을 위 그림에서 확인할 수 있듯이,
설계 절차에서 생성되는 Document가 테스팅 단계의 역순으로 활용된다.
Reference: Software Engineering 10th Edition
(Ian Sommerville 저, Pearson, 2016)
Reference: Object-Oriented Systems Analysis and Design Using UML 4th Edition
(Simon Bennett, Steve McRobb, Ray Farmer 저, McGrawHill, 2010)