Skip to Content
Suffering builds character
아카이브26.mutation Testing돌연변이 테스트6. Mutation Score 해석 가이드

6. Mutation Score 해석 가이드

1. 목표 점수 가이드라인

프로젝트 유형권장 Mutation Score근거
핵심 비즈니스 로직90%+금융 계산, 권한 검증 등 버그 비용이 높은 코드
일반 애플리케이션 코드80%+대부분의 서비스 로직
유틸리티 / 헬퍼70%+단순한 변환, 포맷팅 등
DTO / 데이터 모델측정 불필요getter/setter만 있는 클래스는 돌연변이 테스트 대상에서 제외
💡
Tip

Mutation Score 100%를 맹목적으로 추구할 필요는 없음
100%를 달성하기 위해 의미 없는 테스트를 추가하는 것은 오히려 유지보수 비용만 높임

2. Survived Mutant를 그대로 허용해도 되는 경우

모든 Survived Mutant가 테스트의 결함을 의미하는 것은 아님
다음 경우에는 생존이 허용될 수 있음

동치 돌연변이 (Equivalent Mutant)

변이된 코드가 원본과 동작이 완전히 동일한 경우
어떤 테스트를 작성해도 이 돌연변이를 잡을 수 없음

App.java
// 원본 int index = 0; while (index < list.size()) { process(list.get(index)); index++; } // 변이: index < list.size() → index != list.size() // index가 0부터 1씩 증가하므로 < 와 != 의 결과가 항상 동일 → 동치 돌연변이
💡
Tip

동치 돌연변이는 돌연변이 테스트의 알려진 한계
Pitest는 이를 자동으로 식별하지 못하므로, 리포트에서 수동으로 판단해야 함

로깅 / 디버그 코드

App.java
// 로그 출력이 변이되어도 비즈니스 로직에 영향 없음 logger.info("주문 생성: " + orderId);

3. 흔한 함정

함정 1: Mutation Score만 보고 라인 커버리지를 무시

프로그램 결과 콘솔
Line Coverage: 60% | Mutation Score: 95%

Mutation Score가 높아 보이지만, 테스트가 커버하지 않는 40%의 코드에는 돌연변이가 생성되지도 않았음
→ 커버리지가 없는 코드는 측정 대상에서 빠짐

⚠️
Warning

Mutation Score는 테스트가 커버하는 코드 내에서의 품질 지표로,
라인 커버리지가 낮으면 Mutation Score가 높아도 의미가 제한적임
따라서 두 지표를 함께 봐야 함

함정 2: 테스트 수를 늘리면 Mutation Score가 올라간다는 착각

// 테스트 10개를 추가했지만 모두 같은 패턴 @Test void test1() { assertEquals("A", classify(95)); } @Test void test2() { assertEquals("A", classify(96)); } @Test void test3() { assertEquals("A", classify(97)); } // ... 경계값(90)은 여전히 테스트하지 않음 → Mutation Score 변화 없음

테스트의 수가 아니라 다양성이 중요
→ 경계값, 예외 경로, 다른 분기를 커버하는 테스트를 추가해야 함

함정 3: Mutation Score를 CI에서 강제하면서 임계값을 너무 높게 설정

pom.xml
<!-- 너무 공격적인 설정 --> <mutationThreshold>100</mutationThreshold>

동치 돌연변이 때문에 100%는 현실적으로 달성 불가능한 경우가 많음
빌드가 계속 실패하면 팀이 돌연변이 테스트 자체를 포기하게 됨

💡
Tip

CI에서는 80~85% 정도의 임계값으로 시작하고,
팀이 익숙해지면 점진적으로 올리는 것을 권장

4. Pitest 리포트 활용 워크플로우

  1. Pitest를 실행
  2. 리포트에서 빨간색 라인(Survived Mutant)을 찾음
  3. 해당 라인의 돌연변이 상세를 확인
  4. 판단:
    • 테스트를 추가해야 하는가? → 테스트 작성
    • 동치 돌연변이인가? → 무시 (주석으로 기록)
    • 테스트 불가능한 코드인가? → excludedMethods로 제외
  5. 다시 실행하여 개선 여부 확인

5. Pitest 설정 옵션 참고

옵션설명예시
targetClasses변이 대상 클래스com.example.service.*
targetTests사용할 테스트 클래스com.example.service.*Test
mutators활성화할 MutatorDEFAULTS, ALL
excludedMethods제외할 메서드toString, hashCode
mutationThreshold최소 Mutation Score (CI용)80
timestampedReports타임스탬프 디렉토리 생성false
outputFormats리포트 형식HTML, XML
pom.xml
<configuration> <targetClasses> <param>com.example.service.*</param> </targetClasses> <excludedMethods> <param>toString</param> <param>hashCode</param> <param>equals</param> </excludedMethods> <mutationThreshold>80</mutationThreshold> </configuration>

6. Pitest 요약

돌연변이 테스트는 테스트의 품질을 객관적으로 측정하는 유용한 기법이지만,

명확한 한계점도 존재하기 때문에 숫자 지표에만 집착하기보다는, Survived Mutant가 알려주는 테스트의 빈틈에 집중하는 것이 중요

Last updated on