본문으로 건너뛰기
SDETRole
SDETRole

용어집 · 테스트 기초

뮤테이션 테스트(변이 테스트)

영어: Mutation testing

다른 이름: 변이 테스트, 뮤테이션 테스팅, mutation analysis, mutation score

정의

코드에 작은 버그(뮤턴트)를 의도적으로 심고 테스트를 다시 실행해, 테스트 스위트가 결함을 실제로 잡아내는지 측정하는 기법입니다.

뮤테이션 테스트(Mutation testing)는 테스트를 테스트합니다. 도구는 코드의 복사본을 많이 만들고, 각 복사본에 작은 변경을 하나씩 가합니다. 예를 들어 >=를 >로, +를 -로 바꾸거나, 메서드 본문을 return null로 바꿉니다. 이렇게 변경된 복사본 하나하나를 **뮤턴트(mutant)**라고 합니다. 테스트 스위트는 모든 뮤턴트에 대해 실행됩니다. 테스트가 하나라도 실패하면 그 뮤턴트는 제거된(killed) 것입니다. 모든 테스트가 여전히 통과하면 뮤턴트가 살아남은(survived) 것이며, 이는 테스트가 그 버그를 알아차리지 못한다는 뜻입니다.

뮤테이션 점수(mutation score) = 제거된 뮤턴트 수 / 전체 뮤턴트 수(동등 뮤턴트 제외)

예시

boolean isAdult(int age) {
    return age >= 18;
}

테스트: isAdult(30)은 true, isAdult(10)은 false입니다. 라인 커버리지와 브랜치 커버리지는 모두 100%입니다.

도구가 age > 18인 뮤턴트를 만듭니다. 두 테스트가 여전히 통과하므로 뮤턴트는 살아남습니다. 이로써 경계값 테스트가 빠져 있다는 사실, 즉 아무도 isAdult(18)을 확인하지 않았다는 것이 드러납니다. 이 테스트를 추가하면 뮤턴트가 제거됩니다. 커버리지로는 알 수 없는 사실을 뮤테이션 테스트는 알려 줍니다.

도구

  • Java: PIT(pitest). Maven·Gradle 플러그인과 JUnit 5 지원을 제공합니다.
  • JavaScript/TypeScript: StrykerJS. .NET과 Scala 버전도 있습니다.
  • Python: mutmut, Cosmic Ray.

실무상의 한계

  • 비용. 뮤턴트 하나가 곧 테스트 실행 한 번입니다. 도구는 변경된 라인을 커버하는 테스트만 실행하거나 변경된 코드에 대해 증분 실행하는 방식으로 비용을 줄이지만, 그래도 일반 실행보다 훨씬 느립니다. 대부분의 팀은 커밋마다 전체 코드베이스에 돌리지 않고, 야간에 실행하거나 풀 리퀘스트에서 변경된 파일에만 실행합니다.
  • 동등 뮤턴트(equivalent mutant). 어떤 변경은 동작을 전혀 바꾸지 않습니다. 예를 들어 i가 항상 n보다 작은 값에서 1씩 증가하는 루프에서 i < n을 i != n으로 바꾸는 경우입니다. 어떤 테스트로도 이런 뮤턴트를 제거할 수 없으므로 사람이 검토해서 제외해야 합니다.
  • 단위 테스트 수준에서 가장 효과적입니다. 뮤테이션 테스트는 빠르고 결정적인 단위 테스트를 전제로 설계되었습니다. 느린 UI 테스트에 적용하는 것은 현실적인 경우가 드뭅니다.

완벽한 점수를 쫓기보다는, 살아남은 뮤턴트를 특히 비즈니스 로직에서 빠진 어설션을 찾는 할 일 목록으로 활용하십시오.

SDETRole 전체에서 검색할 내용을 입력하세요.

Pagefind 전문 검색 · 브라우저에서 실행됩니다 검색 페이지 열기 →