블라디미르 코리코프 님의 "단위 테스트" 책을 정리한 포스팅입니다.
1. 테스트 스위트 품질 측정
커버리지 지표
- 테스트에 의해 실행된 코드의 비율
- ✅ 테스트 스위트의 품질을 평가하는데 자주 사용됨
종류
| 항목 | 설명 | 공식 |
| 코드 커버리지 | 전체 코드 중, 테스트 실행 시 실행된 라인의 비율 | 실행된 코드 라인 수 / 전체 코드 라인 수 |
| 분기 커버리지 |
모든 분기가 테스트되었는지 측정
➡️ 코드 커버리지보다 더 정밀하고 정확한 테스트 평가 가능 |
통과한 분기 수 / 전체 분기 수
|
예시) 분기 커버리지
더보기
public boolean isEligibleForDiscount(int age, boolean hasCoupon) {
if (age >= 18) { // 분기 1
if (hasCoupon) { // 분기 2
return true; // 조건이 모두 참일 때
} else {
return false; // 나이 18 이상이고, 쿠폰이 없을 때
}
} else {
return false; // 나이가 18 미만일 때
}
}
| 번호 | 입력 값 | 실행된 분기 |
| 테스트 1 | age = 20 hasCoupon = true |
첫 번째 분기: 참 두 번째 분기: 참 |
| 테스트 2 | age = 20 hasCoupon = false |
첫 번째 분기: 참 두 번째 분기: 거짓 |
| 테스트 3 | age = 15 hasCoupon = true |
첫 번째 분기: 거짓 |
| 테스트 4 | age = 15 hasCoupon = false |
첫 번째 분기: 거짓 |
- 100% 분기 커버리지
- ✅ 전체 분기 커버리지를 달성하려면 모든 조건문이 참/거짓인 경우를 다 테스트해야 함
- ➡️ 위 4개의 테스트 스위트는 모든 분기의 테스트를 커버함
한계
| 구분 | 한계 설명 | 세부 내용 |
|
모든 가능한 결과 검증 불가
|
입력 조합의 무한성 | 모든 입력 경우의 수를 테스트 코드로 커버하기 어려움 |
| 상태 변화 다양성 |
시스템 상태의 모든 변화를 테스트에 포함하는 데 한계가 있음
|
|
|
외부 라이브러리 반영 불가
|
커버리지 지표 한계 |
외부 라이브러리 내부 로직은 커버리지 계산에 포함되지 않음
|
| 내부 조건 누락 |
외부 라이브러리 내부적으로 다양한 조건/분기 처리하지만, 테스트 커버리지에 반영되지 않음
|
|
| 에러 경로 미검증 |
외부 라이브러리 내부 코드 경로에서 발생할 수 있는 에러 상황을 직접 검증해야 함
|
예시) 모든 가능한 결과 검증 불가
더보기
public class LoginService {
public String login(String username, String password) {
if ("user1".equals(username) && "password123".equals(password)) {
return "Login successful";
}
return "Login failed";
}
}
- 입력 조합: 다양한 사용자명과 비밀번호 조합 (너무 많음)
- 상태 변화: 로그인 이후 세션 유지, 타임아웃 등 (단순 커버리지로 보장 안됨)
예시) 외부 라이브러리 반영 불가
더보기
public User parseUser(String json) {
try {
return objectMapper.readValue(json, User.class);
} catch (JsonProcessingException e) {
log.error("잘못된 JSON 입력: {}", json, e);
return null; // 혹은 커스텀 예외 변환
}
}
@Test
void parseUser_validJson() {
String json = "{\"name\":\"Alice\"}";
User user = myService.parseUser(json);
assertEquals("Alice", user.getName());
}
@Test
void parseUser_invalidJson() {
String json = "{invalid-json}";
User user = myService.parseUser(json);
assertNull(user); // 예외를 null 반환으로 처리했는지 검증
}
- 라이브러리 내부에서 어떤 분기로 예외를 던질지 알수 없음
- ➡️ 클라이언트 코드에서 예외 처리 상황에 대한 테스트 필요
2. 성공적인 테스트 스위트
| 항목 | 설명 |
| 개발 주기에 통합 |
- 코드 변경 시 테스트 작성: 코드가 변경될 때마다, 테스트 스위트를 작성하고 실행해야 함
- 빌드 시스템에 통합: 코드 변경 시마다 자동으로 실행되도록 해야 함 |
| 중요한 부분만을 대상으로 | - 비즈니스 로직에 집중: 도메인 모델, 알고리즘을 중심으로 테스트 작성 - 인프라 및 외부 종속성: 테스트 코드에서 분리하고, 해당 부분은 모의 객체를 사용 |
| 최소 유지비용, 최대 가치 |
- 유지비용이 적고, 가치 있는 테스트에 집중하기
- 좋은 코드 설계 필요: 좋은 테스트 코드를 작성하기 위해서는 코드베이스의 설계가 잘 되어 있어야 함 |
'Code > Test' 카테고리의 다른 글
| [단위 테스트] 4-1. 좋은 단위 테스트의 4대 요소: 4대 요소 (0) | 2025.01.19 |
|---|---|
| [단위 테스트] 3. 단위 테스트 구조 (0) | 2025.01.07 |
| [단위 테스트] 2-2. 단위 테스트란 무엇인가: 런던파와 고전파 (1) | 2025.01.07 |
| [단위 테스트] 2-1. 단위 테스트란 무엇인가: 단위 테스트란 (0) | 2025.01.07 |
| [단위 테스트] 1-1. 단위 테스트의 목표: 단위 테스트 목표 (0) | 2025.01.06 |