코드 커버리지(Code Coverage)
1. 코드 커버리지란?
- 테스트 코드가 실제 애플리케이션 코드를 얼마나 실행했는지를 수치로 표현한 지표
- 테스트가 코드 전체에 얼마나 영향을 미치는지 확인 가능
- 코드 안정성, 테스트 신뢰성을 평가하는 데 활용
2. 코드 커버리지가 중요한 이유
- 테스트가 작성되었더라도, 모든 코드 경로가 테스트되는 것은 아님
- 테스트의 범위와 누락된 부분을 식별할 수 있음
- 코드 리팩토링 시, 테스트 커버리지로 안전성 확인 가능
3. 코드 커버리지의 주요 종류
3-1. 구문 커버리지 (Statement Coverage)
- 코드의 각 줄(라인)이 실행되었는지를 확인
- 가장 기본적인 커버리지
- 예: 5줄의 코드 중 5줄 모두 실행되면 100% 달성
public void sayHello(String name) {
System.out.println("Hello");
System.out.println("My name is " + name);
}
- 위 메서드를 테스트하면서 sayHello("Alice")를 호출했다면, 두 줄이 모두 실행되므로 구문 커버리지는 100%가 됨
3-2. 결정 커버리지 (Decision Coverage / Branch Coverage)
- 조건문에서 참/거짓 모든 분기(branch)가 실행되었는지 확인
- 분기되는 흐름이 테스트되었는지를 중점적으로 평가
- 예: if문에서 조건이 true일 때와 false일 때 각각 실행
public String getGrade(int score) {
if (score >= 60) {
return "Pass";
} else {
return "Fail";
}
}
- 테스트 케이스 예시:
- getGrade(70) → if문에서 true 분기 실행
- getGrade(50) → else 분기 실행
- 두 케이스를 모두 실행해야 결정 커버리지 100% 달성
3-3. 조건 커버리지 (Condition Coverage)
- 복합 조건문 내 각 조건이 참/거짓으로 평가되었는지 확인
- 전체 조건식뿐 아니라 조건 구성 요소 각각의 테스트 여부를 확인
public boolean isEligible(int age, boolean hasID) {
return age >= 18 && hasID;
}
- 테스트 케이스 예시:
- isEligible(20, true) → age >= 18 = true, hasID = true
- isEligible(16, true) → age >= 18 = false, hasID = true
- isEligible(20, false) → age >= 18 = true, hasID = false
- 위 테스트 케이스로 각 조건이 참과 거짓 모두로 평가됨 → 조건 커버리지 충족
4. 코드 커버리지는 높을수록 좋은가?
- 일반적으로 높을수록 안정적인 코드라고 판단 가능
- 하지만 커버리지가 높다고 해서 좋은 테스트인 것은 아님
- 단순 실행만 하고 실제 검증이 없는 테스트도 커버리지에 포함됨
- 예외 상황, 경계값, 실패 케이스 등의 테스트가 누락될 수 있음
- 커버리지 수치 + 테스트의 품질 함께 고려해야 함
5. 관련 테스트 개념
| 용어 |
설명 |
| 테스트 코드 |
기능 검증을 위한 코드 |
| 유닛 테스트 (Unit Test) |
하나의 함수 또는 메서드 단위 테스트 |
| 통합 테스트 (Integration Test) |
여러 컴포넌트가 함께 작동하는지 확인 |
| E2E 테스트 (End-to-End Test) |
실제 사용자의 흐름을 시뮬레이션하여 전체 시스템 검증 |