4. 주요 Mutator 개요
Pitest의 기본 Mutator 그룹에는 7가지 변이 규칙이 포함되어 있음
각 Mutator가 코드를 어떻게 변이시키는지, 그리고 어떤 테스트로 잡을 수 있는지 정리
1. 대표적인 돌연변이(Mutator) 종류
Pitest는 다음과 같은 돌연변이 클래스를 제공함
| # | Mutator | 변이 대상 | 변이 예시 | 탐지 전략 |
|---|---|---|---|---|
| 1 | Conditionals Boundary | < <= > >= | >= → > | 경계값 정확히 테스트 |
| 2 | Negate Conditionals | == != < > <= >= | >= → < | 조건 양쪽에서 반환값 검증 |
| 3 | Math | + - * / % | * → / | 계산 결과를 구체적 값으로 검증 |
| 4 | Increments | ++ -- | i++ → i-- | 증감 후 값을 정확히 검증 |
| 5 | Invert Negatives | -value (단항) | -x → x | 부호가 있는 입력으로 결과 검증 |
| 6 | Return Values | return 문 | return true → return false | 반환값을 구체적으로 검증 |
| 7 | Void Method Call | void 메서드 호출 | 호출 제거 | 부수 효과(side effect) 검증 |
2. Conditionals Boundary Mutator
비교 연산자의 경계를 한 단계 이동시킴
| 원본 | 변이 |
|---|---|
< | <= |
<= | < |
> | >= |
>= | > |
Sample.java
// 원본
if (score >= 90) { return "A"; }
// 변이: >= → >
if (score > 90) { return "A"; }
// score=90일 때 원본은 "A", 변이는 "B" → 경계값 테스트로 탐지💡
Tip
탐지 핵심: 경계값 자체(90)와 경계 바로 옆(89, 91)을 모두 테스트
3. Negate Conditionals Mutator
조건식 전체를 반전시킴
| 원본 | 변이 |
|---|---|
== | != |
!= | == |
< | >= |
>= | < |
> | <= |
<= | > |
Sample.java
// 원본
if (status == OrderStatus.CONFIRMED) { ... }
// 변이: == → !=
if (status != OrderStatus.CONFIRMED) { ... }
// CONFIRMED 상태와 다른 상태 모두에서 동작을 검증해야 탐지 가능💡
Tip
탐지 핵심: 조건이 참인 경우와 거짓인 경우 모두에서 서로 다른 결과를 검증
4. Math Mutator
산술 연산자를 반대 연산자로 교체
| 원본 | 변이 |
|---|---|
+ | - |
- | + |
* | / |
/ | * |
% | * |
Sample.java
// 원본
double total = price * quantity;
// 변이: * → /
double total = price / quantity;
// price=100, quantity=10이면 원본 1000, 변이 10 → 구체적 값 검증으로 탐지⚠️
Warning
assertDoesNotThrow나 assertNotNull로는 Math 변이를 절대 잡을 수 없음.
반드시 assertEquals로 계산 결과를 검증해야 함
5. Increments Mutator
증감 연산자를 반대로 바꿈
| 원본 | 변이 |
|---|---|
i++ | i-- |
i-- | i++ |
++i | --i |
--i | ++i |
Sample.java
// 원본
for (int i = 0; i < n; i++) {
count++;
}
// 변이: count++ → count--
// n=3이면 원본 count=3, 변이 count=-3 → 결과값 검증으로 탐지💡
Tip
탐지 핵심: 루프나 카운터의 최종 결과값을 정확히 검증
6. Invert Negatives Mutator
단항 부정 연산자(-)를 제거
| 원본 | 변이 |
|---|---|
-value | value |
Sample.java
// 원본
public double negate(double x) {
return -x;
}
// 변이: -x → x
// negate(5.0)이면 원본 -5.0, 변이 5.0 → 부호 검증으로 탐지💡
Tip
탐지 핵심: 양수 입력을 넣고 결과가 음수인지 검증.
0을 입력하면 -0 == 0이므로 탐지할 수 없음
7. Return Values Mutator
반환값을 다른 값으로 교체. 반환 타입에 따라 변이 규칙이 다름
| 반환 타입 | 원본 | 변이 |
|---|---|---|
boolean | true | false (그리고 반대) |
int | 0이 아닌 값 | 0 |
int | 0 | 1 |
double | 0이 아닌 값 | 0.0 |
Object | non-null | null |
String | 문자열 | "" (빈 문자열) |
Sample.java
// 원본
public boolean isPalindrome(String s) {
return reversed.equals(s); // true 또는 false
}
// 변이: true → false
// "aba"를 입력하면 원본 true, 변이 false → assertTrue로 탐지💡
Tip
탐지 핵심: 반환값을 assertEquals, assertTrue, assertFalse로 구체적으로 검증.
assertNotNull만으로는 부족
8. Void Method Call Mutator
void 메서드 호출을 통째로 제거
Sample.java
// 원본
public void updateOrderStatus(Order order, OrderStatus newStatus) {
// ... 유효성 검증 ...
order.setStatus(newStatus); // void 메서드 호출
}
// 변이: order.setStatus(newStatus) 호출 제거
// 메서드 실행 후 order.getStatus()가 변경되었는지 검증해야 탐지 가능⚠️
Warning
void 메서드는 반환값이 없으므로, 부수 효과(side effect) 를 검증해야 함 객체의 상태 변경, 컬렉션 수정, 외부 시스템 호출 등이 실제로 일어났는지 확인
Last updated on