PHpullh
학습 라이브러리/Kotlin/뮤테이션 테스트 (Mutation Testing)

KOTLIN · 테스트

뮤테이션 테스트 (Mutation Testing)

코드를 의도적으로 변형하여 테스트가 실패하는지 검증합니다. 테스트의 품질을 측정하는 기법입니다.

테스트고급mutation-testingtest-qualitypitestcode-coverage

핵심 설명

코드를 의도적으로 변형하여 테스트가 실패하는지 검증합니다. 테스트의 품질을 측정하는 기법입니다.

Kotlin code

// 테스트 대상
fun isLeapYear(year: Int): Boolean =
    (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)

// 뮤턴트 생성 (코드 변형)
fun isLeapYearMutant1(year: Int): Boolean =
    (year % 4 == 0 && year % 100 != 0) || (year % 400 != 0) // != → ==

fun isLeapYearMutant2(year: Int): Boolean =
    (year % 4 == 0 || year % 100 != 0) || (year % 400 == 0)  // && → ||

fun isLeapYearMutant3(year: Int): Boolean =
    (year % 4 != 0 && year % 100 != 0) || (year % 400 == 0) // == → !=

// 테스트 스위트
val testCases = listOf(
    2000 to true, 1900 to false, 2024 to true,
    2023 to false, 1600 to true, 100 to false
)

fun runTests(name: String, impl: (Int) -> Boolean): Boolean {
    return testCases.all { (year, expected) ->
        val result = impl(year) == expected
        if (!result) println("  뮤턴트 $name 탐지: year=$year")
        result
    }
}

fun main() {
    println("원본 테스트: ${if (runTests("원본", ::isLeapYear)) "통과" else "실패"}")
    println()

    val mutants = mapOf(
        "Mutant1(!=→==)" to ::isLeapYearMutant1,
        "Mutant2(&&→||)" to ::isLeapYearMutant2,
        "Mutant3(==→!=)" to ::isLeapYearMutant3,
    )

    var killed = 0
    mutants.forEach { (name, impl) ->
        val survived = runTests(name, impl)
        if (!survived) { killed++; println("  ✓ $name 제거됨") }
        else println("  ✗ $name 생존! (테스트 부족)")
    }
    println("
뮤테이션 점수: $killed/${mutants.size} (${killed * 100 / mutants.size}%)")
}

학습 팁

PIT(pitest) 라이브러리를 사용하면 자동으로 뮤턴트를 생성하고 테스트 스위트의 품질을 측정합니다.

주의할 점

뮤테이션 테스트에서 생존한 뮤턴트는 테스트가 부족하다는 의미입니다. 해당 분기를 검증하는 테스트를 추가하세요.

자주 묻는 질문

뮤테이션 테스트 (Mutation Testing)란 무엇인가요?

코드를 의도적으로 변형하여 테스트가 실패하는지 검증합니다. 테스트의 품질을 측정하는 기법입니다.

뮤테이션 테스트 (Mutation Testing) 학습 시 주의할 점은 무엇인가요?

뮤테이션 테스트에서 생존한 뮤턴트는 테스트가 부족하다는 의미입니다. 해당 분기를 검증하는 테스트를 추가하세요.