V&V, White Box Coverage
이번 포스트에서는 V&V (Verification and Validation) 에 대해 다룬다. 그리고 White Box Coverage 에 대해 자세히 다루려고 한다.
V&V (Verification and Validation)
V&V 란?
- 소프트웨어 개발 생명주기 전체에 걸쳐서 수행되는 과정
- 목적
- Verification
- 개발 프로세스의 각 단계가 올바르게 수행되었는가?
- 주로 검토 (Inspection), 리뷰 (review) 중심으로 이루어진다.
- Validation
- 산출물이 이전 단계의 요구사항을 충족하는가?
- 주로 testing 중심인 동적 방법으로 검증한다.
Insepction
- 정적 시스템 표현 분석 => 문제 발견
- 시스템을 실행하지 않아도 검증이 가능하다.
- 요구사항 문서, 설계 문서, 구성 데이터, 테스트 데이터 등에도 적용이 가능하다.
- 장점
BKM (Best Known Method) : 설계 및 코드의 50~90%의 결함을 제거할 수 있다.
이는 곧 테스트 비용을 절감해준다. => 테스트 대비 경제적 효과가 크다.
Program Testing
- 동적 검증
- 프로그램이 의도한 기능을 수행하는지를 검증한다.
- 실험을 통해서 오류를 발견한다.
- 핵심 : 오류의 존재는 검증이 가능하지만, 부재는 보장이 불가하다.
Inspections 과 Testing은 상호보완적으로 사용해야 한다.
-> V&V는 두 가지의 접근이 모두 활용이 필요하기 때문이다.
Testing Stages
- 소프트웨어 테스트는 단계적으로 수행된다.
| 단계 | 목적 |
|---|---|
| Development Testing | 개발자가 수행 → 초기 결함 제거 |
| Release Testing | 시스템 버전 테스트 → 고객 요구사항 충족 검증 |
| User Testing | 실제 사용 환경에서 고객/사용자가 테스트 |
Development Testing
- 개발 단계 테스트로 주로 개발자가 수행한다.
- 목적은 크게 2가지이다.
- 프로그램 오류를 검출한다.
- 요구사항을 충족하는지 검증한다.
- 3가지의 주요 테스트를 수행한다.
- 1. Unit Testing
-
프로그램의 개별 구성요소 (함수, 클래스 등)를 테스트 한다.
- 2. Component Testing
-
여러 유닛을 결합한 컴포넌트 단위를 테스트 한다.
- 3. System Testing
-
전체 시스템이 요구사항을 충족하는지 테스트 한다.
개발 단계에서 점진적으로 테스트 범위를 넓혀가는 구조이다.
Black box vs Whit box Testing
Black box Testing
- 테스트를 진행할 때 시스템 내부 구조를 고려하지 않는다.
-
입력 -> 출력 결과만 보고 테스트를 수행한다.
- 설계 명세기반으로 테스트하여 요구사항이 충족하는지에 대한 여부를 확인하는데 용이하다.
- 사용자의 관점에서 테스트 가능
주로 기능 테스트, 요구사항 기반 테스트에서 사용된다.
White box Testing
- 테스트 시 시스템 내부 구조를 고려하여 테스트를 설계한다.
- 모든 경로/ 조건 등을 고려해 구현 코드를 기반으로 테스트를 설계한다.
-
경로 커버리지 확보가 가능하여 숨겨진 내부 오류를 검출할 수 있다.
- 단점: 테스트 비용이 높아지고, 내부 구현 변경시 테스트 케이스도 변경해야 한다.
주로 단위 테스트, 개발자 테스트에서 활용한다.
Equivalence Partitioning
- 등가 분할 테스트
- 입력 값의 범위 전체를 테스트 하는 것은 불가능하다.
- 너무 많은 경우의 수가 존재하기 때문이다.
- 동일하게 동작할 것 같은 그룹을 나눈다. (Partitioning)
- 각 그룹에서 대푯값만 선택하여 테스트 한다.
더 효율적으로 테스트 케이스를 줄이고 테스트를 할 수 있다.
Test Coverage (for White Box Testing)
Code Coverage란?
-
테스트가 소스 코드의 얼마만큼을 실행했는지를 측정하는 지표
-
작성한 테스트 케이스(Test Suite)가 소스 코드의 어느 부분까지 실행/검증했는지를 보는 것
-
왜 중요할까?
- 테스트가 모든 기능을 충분히 검증했는지 확인하기 위해서 사용된다.
- Code coverage가 낮으면 테스트되지 않은 코드 영역이 많다. (숨은 버그 가능성이 높다.)
- Code coverage가 높으면 테스트가 코드 대부분을 실행했음을 의미하여 테스트 신뢰성이 높다.
-
종류
Coverage 종류 설명 Function Coverage 모든 함수가 실행되었는가 Statement Coverage (Node Coverage) 모든 코드 라인이 실행되었는가 Branch Coverage (Decision/Edge Coverage) 모든 분기(if 등)의 True/False가 실행되었는가 Condition Coverage (Predicate Coverage) 각 Boolean 조건이 True/False로 평가되었는가 Condition/Decision Coverage Condition + Branch Coverage Modified Condition/Decision Coverage (MCDC) 각 조건이 결과에 독립적으로 영향을 미치는지 확인 Multiple Condition Coverage 모든 조건 조합을 테스트
Statement Coverage
- 프로그램 내 모든 “Statement(문장)”가 최소 한 번은 실행되는지 확인하는 Coverage 기준
Statement 란 -> 코드에서 각 실행 가능한 문장
- 목적
- 모든 Statement가 테스트 케이스에 의해 실행되는지 확인
- Statement Coverage가 낮으면 테스트 되지 않은 코드 영역이 존재함을 의미한다.
- 특징
- 테스트 구성이 쉽고 빠르다. (단순히 Statement가 실행만 되면 된다.)
- 코드 누락 탐지가 가능하다.
- if-else 같은 조건 분기에서 충분히 테스트를 하지 않을 가능성이 존재한다.
- 기본적인 시작점이다.
- 더 높은 수준으로 확장이 필요하다.
Branch Coverage
- 모든 분기 (Branch), 즉 if-else 조건의 각 방향 (True/ False)이 테스트 케이스에서 적어도 한 번은 실행되는지 확인하는 Coverage 기준
- Branch란? “조건문(if-else, switch문 등)에서 가능한 실행 경로”
- 목적
- 모든 조건의 모든 분기 경로가 테스트되는지 확인한다.
- 조건이 True, False 인 경우 모두 실행하도록 테스트를 구성한다.
- 특징
- Statement Coverage 보다는 더 엄격한 Coverage이다.
- 조건 논리 오류 검출이 가능하다.
- 조건문 분기를 모두 테스트가 가능하다. (조건 내에 복잡한 논리 (AND / OR)은 커버하지 못한다.)
- Branch Coverage를 만족하면 자동적으로 Statement Coverages는 100% 만족한다.
Condition Coverage
- 복합 조건문 내 개별 Booelan 조건 각각이 True / False로 평가되는지 확인하는 Coverage 기준
- Branch Coverage의 한계인 조건 내부 세부 조건을 해결 가능
- 목적
- 복작한 조건문 내부에서 모든 Boolean 조건이 양 방향으로 평가되는지 확인한다.
- 조건 내부의 논리 오류(AND / OR)를 더 정밀하게 탐지가 가능하다.
- 특징
- 복합 조건문 내부 오류를 검출 가능하다.
- 전체 if 문 논리 흐름의 검증과는 별개이다.
- AND / OR 조합 오류 탐지가 가능하다.
- 조건 간의 상호작용은 탐지가 불가능하다.
- Condition Coverage가 Branch Coverage보다 더 세밀한 검증을 제공하는 것은 맞지만, 두 개의 Coverage는 서로 독립적이다.
- 즉 하나가 100%여도 다른 것이 100%가 아닐 수 있다.
- 복합 조건문 내부 오류를 검출 가능하다.
Condition / Decision Coverage
- Branch Coverage (Decision Coverage) + Condition Coverage를 동시에 만족하는 Coverage 기준
- 전체 조건문의 결과 (True / False)도 모두 테스트 해야 한다.
- 조건문 내부의 모든 조건이 True / False로 모두 평가되는 것도 테스트 해야 한다.
- 목적
- Branch Coverage와 Condition Coverage로 각각의 모든 경우를 실행되는지 확인할 수가 없다.
- 둘을 동시에 충족해야 더 강력한 논리 오류 탐지가 가능하다.
- 특징
- 논리 오류 탐지에 강력하다. (테스트 케이스 수가 많아지기는 한다.)
- 실무에서 많이 사용된다.
Multiple Condition Coverage
- 조건문 내 모든 개별 조건들의 가능한 모든 조합을 테스트하는 Coverage 기준
- 목적
- Condition Coverage는 각 조건이 True / False로 평가되었는지 확인을 할 수 있지만, 조건들 간의 조합까지는 확인하지 않는다.
- 조건들 간 모든 조합을 테스트하여 논리적 오류 탐지 가능성을 최대화한다.
- 특징
- 조건 간 모든 논리 조합 검증이 가능하기에 가장 강력한 Coverage이다.
- 논리 오류 탐지율이 최고여서 현실적으로는 어려울 수 있다.
MCDC
-
각 개별 조건이 전체 조건문의 결과 (Decision)에 독립적으로 영향을 미치는지 확인하는 Coverage 기준
-
목표
- 조건문 내의 각 조건이 전체 결과에 영향을 주는지 확인한다.
- 조건문 전체 결과(True / False)가 특정 조건 하나의 변화만으로 바뀌는 테스트 케이스가 존재해야 한다.
- 조건마다 독립적인 영향력을 테스트
-
특징
- Multiple condition Coverage로는 모든 조건 조합이 테스트가 가능하지만 이는 테스트 케이스가 너무 많은 문제점이 존재한다.
그보다 훨씬 적은 테스트 케이스로 충분히 강력한 검증을 제공한다.
- MCDC는 Multiple Condition Coverage(2의 n승 개의 테스트)보다 작은 테스트 케이스를 가진다.
- n + 1개에서 2의 n승까지 필요로 한다.
- 실무에서 가장 현실적이고 강력하다.
부록 : Coverage Comparison
