좋은 소프트웨어의 좋은 품질 기능은 테스트 범위입니다. 테스트가 포함된 프로덕션 코드 라인의 높은 적용 범위(또는 적용 범위라고도 함)는 쉽게 편집할 수 있는 버그 및 코드, 키워드 “리팩토링”이 적다는 것을 의미합니다. 그러나 이것은 오판입니다. 100%의 적용 범위라도 오류 없는 소프트웨어 또는 테스트 품질에 대한 정보를 제공하지 않습니다.
코드 커버리지가 충분하지 않은 이유는 무엇입니까?
커버리지는 자동화된 테스트에 의해 실행되는 생산적인 코드 라인 수를 측정한 것입니다. 여기에서 중요: 테스트에서 메서드를 실행하는 것으로 충분하며 이 메서드는 테스트에서 단일 어설션 없이, 즉 메서드의 예상 반환 값과 실제 반환 값 사이의 비교 없이 이미 “커버리지”를 갖습니다.
해외 개발 팀에 100% 테스트 커버리지를 요구한 유럽 대기업에 대한 잘 알려진 일화가 있습니다. 그런 다음 어설션 없이 테스트 스위트의 모든 메서드를 호출했으며 오류 없는 테스트로 100% 테스트 커버리지를 달성했습니다. 따라서 테스트 맥락에서 커버리지가 고려하는 유일한 측면은 코드의 어떤 부분이 호출되는지입니다. 이는 코드 부분도 오류 없이 작동한다고 보장하지 않습니다.
그러나 충분한 어설션을 포함하는 좋은 테스트 도구 모음도 높은 테스트 품질을 보장하지 않습니다. 여기서 기본적인 문제는 자동화된 테스트가 코드의 모든 실행 경로가 실제로 적용되는지 여부에 대한 정보를 아직 제공하지 않는다는 것입니다. 즉, 자동화된 테스트는 메서드의 “If” 부분을 확인하지만 “Else” 부분은 확인하지 않을 수 있습니다. 설상가상으로, 개발자가 기존 코드를 변경하면 오류가 발생할 수 있습니다. 예를 들어 >= 쿼리가 잘못 > 쿼리가 됩니다. 해당 테스트가 이 오류와 “빨간색”을 감지할 수 있습니까, 아니면 이 버그에도 불구하고 테스트가 “녹색”으로 유지됩니까? 첫 번째 경우에는 상응하는 높은 테스트 품질이 있고 두 번째 경우에는 그렇지 않습니다.
솔루션 – 돌연변이 테스트
기본 원칙은 수십 년 전에 과학적으로 분석되고 제시되었습니다(참조: R. Lipton, “Fault Diagnosis of Computer Programs,” Student Report, Carnegie Mellon University, 1971).
아이디어는 간단합니다. 소프트웨어 테스트는 생산 코드의 오류를 발견하는 데 사용됩니다. 이러한 오류는 일반적으로 이러한 오류를 구현하는 개발자의 손에서 발생합니다(대개 무의식적으로). 따라서 이전에 녹색이었던 테스트는 이에 상응하는 높은 품질로 작성된 경우, 즉 높은 테스트 품질을 가진 경우 빨간색이 되어야 합니다. 소프트웨어 테스트의 테스트 품질을 확인하기 위해 의도적으로 버그를 생성하는 것은 상대적으로 시간이 많이 걸리고 복잡하기 때문에 자동화된 방식으로 코드를 인위적으로 버그로 수정합니다. 따라서 원래 코드는 “변형”됩니다.
이러한 코드 변형이 자동으로 생성되면 수정되지 않은 테스트 스위트가 (현재 변형된) 코드에 대해 다시 실행됩니다. 여기서 기본 가정은 테스트가 원래 코드에서 녹색이었다면 의도적으로 생성된 버그로 인해 실패하고 빨간색으로 바뀌어야 한다는 것입니다. 그렇지 않은 경우 테스트가 올바르게 테스트되지 않았음을 의미합니다. 즉, 테스트 품질이 좋지 않거나 해당 오류를 차단할 수 있는 테스트가 없습니다.
이 경우 돌연변이에서 녹색에서 빨간색 테스트로 점프하는 것은 의도적입니다. 또한 돌연변이가 죽었다(“죽었다”)고도 합니다. 따라서 의도적으로 도입된 버그에도 불구하고 테스트가 녹색으로 유지되는 다른 경우는 원하지 않습니다. 이를 살아남은 돌연변이라고 합니다.
어떤 버그가 도입되었나요?
Java 세계에서 PIT Mutation은 자동화된 돌연변이 범위 분석을 위한 입증된 도구이며 Maven 및 Gradle 환경에서 사용할 수 있습니다. 빌드 프로세스에서 원본 소스 코드에서 파생된 새로운 “변형”이 생성됩니다. 원래 코드를 분석하고 예를 들어 “>=” 비교 대신 “>” 비교를 사용하는 미리 정의된 뮤테이터 세트가 사용됩니다. 또 다른 예는 부울 반환 값이 주어지면 도구가 단순히 메서드의 반환 값을 반전시키는 것입니다.
돌연변이 검사의 장단점
돌연변이 테스트는 소프트웨어의 품질을 평가할 때 여러 가지 이점이 있습니다. 이 경우 품질 측면은 테스트 도구 모음의 훨씬 더 나은 테스트 품질에 반영됩니다. 돌연변이 테스트의 사용은 다음 원칙을 보여줍니다.
- 돌연변이 테스트는 프로덕션 코드를 테스트하지 않고 테스트 스위트를 테스트합니다.
- 돌연변이 테스트는 주로 테스트 범위와 테스트 품질의 부족을 드러냅니다.
- 돌연변이 테스트는 불필요한 코드를 줄이는 데 도움이 될 수 있습니다.
- 버그를 찾는 것은 돌연변이 테스트의 이차적이고 부수적인 효과일 뿐입니다.
어쨌든 순수한 테스트 커버리지(coverage)는 더 이상 최신 고품질 코드의 품질 척도 역할을 해서는 안 됩니다. 돌연변이 적용 범위는 의미 있는 대안을 제공하며 오늘날 모든 CI/CD 파이프라인에서 누락되어서는 안 됩니다.
그러나 언제나 그렇듯 단점이 없는 장점은 없습니다. 테스트가 빨라야 한다는 테스트 중심 소프트웨어 개발의 신조는 돌연변이 테스트에 의해 다소 제약을 받습니다. 변이 코드를 생성하고 각 개별 변이에 대해 전체 테스트 스위트를 실행하면 테스트 실행 시간이 몇 배로 늘어납니다. 이는 모놀리식 프로젝트의 대규모 코드 기반에서 특히 중요할 수 있습니다.
그럼에도 불구하고 모든 최신 소프트웨어 프로젝트에서 돌연변이 테스트를 빼놓을 수 없으며 그만한 가치가 있습니다.
어떤 돌연변이 테스트 도구를 사용할 수 있습니까?
Java 유니버스에서 Gradle/Maven, JaCoCo(클래식 커버리지 도구) 및 PIT 변형을 사용한 구성은 옵션입니다.