Pitest
Pitest (PITest, PIT Mutation Testing) 는 자바 기반의 Mutation Testing 도구로, 코드의 테스트 커버리지뿐만 아니라 테스트의 효율성을 평가하는 데 사용됩니다. 일반적인 코드 커버리지는 테스트가 코드의 각 부분을 실행했는지 확인하지만, Pitest는 테스트가 코드의 동작을 올바르게 검증하는지도 평가합니다.
Mutation Testing이란?
Mutation Testing은 코드를 변형(뮤테이션)하여 테스트의 견고성을 측정하는 기법입니다. 변형된 코드(뮤턴트)가 올바르게 테스트에 의해 검출(실패)된다면, 테스트가 효과적으로 작성되었다고 판단할 수 있습니다.
Pitest의 작동 방식
- 기본 코드 분석: Pitest는 코드와 테스트를 분석하여 적용 가능한 뮤턴트 연산자를 선택합니다.
- 뮤턴트 생성: 코드에 다양한 변형(뮤턴트)을 적용합니다.
- 조건문 반전 (> → < 또는 ==)
- 산술 연산자 변경 (+ → -)
- 리턴 값 수정 (리턴 값 변경)
- 상수 변경 (1 → 0)
- 테스트 실행: 생성된 뮤턴트를 포함한 코드를 기존 테스트 케이스로 실행하여 테스트가 실패하는지 확인합니다.
- 결과 분석:
- 죽은 뮤턴트 (Killed Mutant): 테스트가 실패하여 뮤턴트가 검출된 경우.
- 살아남은 뮤턴트 (Survived Mutant): 테스트가 통과하여 검출되지 않은 경우.
- 무의미한 뮤턴트 (Equivalent Mutant): 논리적으로 기존 코드와 동일한 변형(검출 불가능).
Pitest의 주요 기능
- 효율적인 테스트 평가:
- 테스트 커버리지뿐만 아니라, 테스트가 얼마나 신뢰할 수 있는지를 평가.
- 자동화된 프로세스:
- Maven, Gradle과 쉽게 통합 가능하여 CI/CD 파이프라인에 적용.
- 플러그인 지원:
- JUnit, TestNG 등 다양한 테스트 프레임워크를 지원.
- 자세한 리포트:
- 생존한 뮤턴트, 죽은 뮤턴트, 테스트 커버리지 등의 리포트 제공.
Pitest를 사용해야 하는 이유
1
2
3
4
5
6
1. **테스트 품질 향상:**
* 단순히 코드 라인을 실행하는 것이 아닌, 코드의 로직을 실제로 검증하는 테스트를 작성하도록 유도.
2. **버그 검출 능력 강화:**
* 테스트가 놓친 잠재적 결함을 찾아낼 수 있음.
3. **CI/CD 파이프라인 강화:**
* 테스트 신뢰성을 높여 프로덕션 품질 개선.
Java, Spring, Gradle 환경에서 Pitest 사용하기
Gradle에서 Pitest 설정
1. Pitest 플러그인 추가
Pitest Gradle 플러그인을 build.gradle
파일에 추가하세요.
Groovy DSL (build.gradle):
1
2
3
plugins {
id 'info.solidsoft.pitest' version '1.9.11' // 최신 버전 확인
}
2. Pitest 설정 추가
Pitest를 build.gradle
에 구성합니다.
Groovy DSL (build.gradle):
1
2
3
4
5
6
7
pitest {
testPlugin = 'junit5' // JUnit 5 사용 시
targetClasses = ['com.yourpackage.*'] // 테스트할 클래스 패키지 지정
threads = 4 // 병렬 실행 쓰레드 수
mutationThreshold = 80 // 뮤턴트 커버리지 목표 (퍼센트)
verbose = true // 상세 로그 출력 활성화
}
3. 플러그인 의존성 추가
테스트 프레임워크에 맞는 플러그인을 추가하세요.
JUnit 5 예시:
1
2
3
dependencies {
pitest 'org.pitest:pitest-junit5-plugin:1.1.2' // JUnit 5 플러그인
}
Pitest 실행
Gradle 명령어를 사용해 Pitest를 실행하세요:
1
./gradlew pitest
실행 결과
결과는 기본적으로 build/reports/pitest
디렉토리에 HTML 형식으로 생성됩니다. 브라우저에서 파일을 열어 결과를 확인하세요.
결과 리포트 이해하기
- Mutation Coverage: 죽은 뮤턴트의 비율.
- Survived Mutants: 테스트가 검출하지 못한 뮤턴트 (테스트 부족 가능성 표시).
- Killed Mutants: 테스트가 검출한 뮤턴트.
- No Coverage: 테스트로 실행되지 않은 코드.
Gradle 프로젝트에서 최적화
1. 테스트 성능 최적화
threads
값을 늘려 병렬로 테스트를 실행하세요:
1
threads = 8
2. 제외할 클래스나 메서드 지정
테스트가 필요 없는 코드를 제외하세요:
1
2
excludedClasses = ['com.yourpackage.util.*'] // 제외할 클래스 패턴
excludedMethods = ['toString', 'hashCode'] // 제외할 메서드
3. 목표 커버리지 설정
목표 커버리지 기준을 설정하여 기준 미달 시 빌드가 실패하도록 구성하세요:
1
mutationThreshold = 85 // 목표 뮤턴트 커버리지
Pitest의 장점
- 로직 테스트 강화: 생존 뮤턴트를 분석해 테스트의 빈틈을 찾아낼 수 있습니다.
- CI/CD 통합: CI 파이프라인에서 정기적으로 테스트를 실행해 품질을 유지합니다.
- 리팩토링 검증: 리팩토링 전후의 Pitest 결과를 비교하여 테스트 효율성을 유지합니다.
Pitest 결과 해석
1
2
3
* **Mutation Coverage:** 뮤턴트가 죽은 비율 (높을수록 좋음).
* **Survived Mutants:** 생존한 뮤턴트. 이 숫자가 높으면 테스트를 강화해야 함.
* **Killed Mutants:** 테스트가 잡아낸 뮤턴트.
This post is licensed under CC BY 4.0 by the author.