뮤테이션 테스팅(Mutation Testing)은 프로덕션 코드에 의도적인 버그(변이/뮤턴트)를 심고, 테스트가 해당 변이를 탐지(kill)하는지 측정하여 테스트 스위트 품질을 평가하는 기법이다.
핵심 개념
원본 코드: if (x > 0)
뮤턴트 1 (경계): if (x >= 0) ← AOR (산술 관계 연산자)
뮤턴트 2 (반전): if (x <= 0)
뮤턴트 3 (상수): if (x > 1)
테스트가 뮤턴트 동작을 원본과 다르게 감지 → "kill"
테스트가 뮤턴트를 구분 못함 → "survive" (테스트 부족)
Mutation Score = killed / (killed + survived) × 100%
변이 연산자 종류
| 연산자 | 예시 |
|---|
| AOR | + → -, * → / |
| ROR | > → >=, == → != |
| COR | && → ` |
| SVR | 상수 값 변경 1 → 0 |
| SOR | return 문 제거 |
typescript
// stryker.config.json
{
"mutate": ["src/**/*.ts"],
"testRunner": "jest",
"reporters": ["html", "clear-text"],
"thresholds": { "high": 80, "low": 60, "break": 50 }
}
// 실행: npx stryker run
// 결과 예시
// 14 mutants tested
// Killed: 11 (78.57%)
// Survived: 3
//
// Surviving mutant:
// src/math.ts:5 (x > 0) → (x >= 0) [SURVIVED]
// → if (x === 0) 케이스 테스트 추가 필요
주요 도구
커버리지 100% + Mutation Score 50%:
→ 코드를 실행하지만 결과를 검증 안 함
커버리지 80% + Mutation Score 85%:
→ 더 의미 있는 테스트
결론: 뮤테이션 점수가 테스트 품질의 더 강한 지표
관련 문서
- •[code-coverage|[코드 커버리지]]
- •[[property-based-testing|속성 기반 테스팅]]
- •[[test-doubles|테스트 더블]]