프로그램의 논리적인 복잡도를 정량적으로 측정하기 위해 제공되는 메트릭
Tom McCabe가 제안한 메트릭 (V(G)). 프로그램 제어 흐름 그래프의 독립적인 경로 수를 계산하여 복잡도와 최소 테스트 수를 동시에 도출한다.
계산 공식
플로우 그래프(Flow Graph)에서 다음 3가지 공식이 모두 동일한 값을 산출한다.
| 공식 | 의미 |
|---|---|
| V(G) = R | R = 노드들로 둘러싸인 영역과 그래프 밖 영역의 수 |
| V(G) = E - N + 2 | E = Edge(화살표) 수, N = Node 수 |
| V(G) = P + 1 | P = Predicate(조건) 노드 수 |
예시
성적 관리 프로그램:
- R = 3
- E - N + 2 = 9 - 8 + 2 = 3
- P + 1 = 2 + 1 = 3
→ V(G) = 3, 최소 3개 이상의 독립 경로를 테스트해야 전체 내부 구조를 커버.
조건 연산자 처리
하나의 if 조건 안에 &&·|| 단락 평가 연산자가 있으면 각 연산자마다 +1. 단락 평가가 추가 분기를 만들기 때문.
int aFunction() { // 기본 1
int A = 0;
if (A && B) { /*...*/ } // if(+1) + &&(+1)
if (C || D) { /*...*/ } // if(+1) + ||(+1)
return 0;
} // V(G) = 5SEI 신뢰성 위험도 기준
SEI(Software Engineering Institute)가 정의한 순환 복잡도 구간별 해석:
| 순환 복잡도 | 신뢰성(Reliability) 위험도 |
|---|---|
| 1~4 | 단순한 프로그램 / Little risk |
| 5~10 | 잘 구조화된 프로그램 / Little risk |
| 11~20 | 다소 복잡한 프로그램 / Moderate Risk |
| 21~50 | 매우 복잡한 프로그램 / High risk |
| > 50 | 테스트 불가능한 프로그램 / VERY HIGH RISK |
수정 시 추가 에러 발생 확률
기존 에러 수정 시 새 에러를 유입시킬 확률이 복잡도와 함께 급증:
| 순환 복잡도 | 추가 에러 발생 확률 |
|---|---|
| 1~10 | 5% |
| 20~30 | 20% |
| 50 이상 | 40% |
| 100 이상 | 60% |
→ 복잡도 50 이상 함수는 리팩토링 없이 수정하면 40% 확률로 회귀 결함을 낳는다.
기준치
| 표준/조직 | 기준 |
|---|---|
| JSF AV C++ Coding Standard | 20 이하 |
| Microsoft | 15 = 리팩토링 한계치, 10 초과 시 리팩토링 고려 |
| HIS Source Code Metrics (자동차) | 1-10 |
| 자동차 도메인 | 10 이하 통과 / 10~30 조건부 통과 / 30 초과 반드시 수정 |
Basis Path Coverage와의 관계
화이트박스 테스팅의 경로 커버리지(Basis Path Coverage) 4단계 중 2단계가 순환 복잡도 계산이다.
- Flow Graph 작성
- 순환 복잡도 계산
- 독립 경로 정의 (V(G)개)
- 테스트 케이스 작성
→ V(G) = 테스트 케이스의 최소 수 (구조 커버리지 100% 보장).