Что такое мутационное тестирование и какова его цель?

«Что такое мутационное тестирование и какова его цель?» — вопрос из категории Тестирование, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Мутационное тестирование — это метод оценки качества набора тестов (например, юнит-тестов) путём внесения небольших, осмысленных изменений (мутаций) в исходный код и проверки, «отлавливают» ли эти изменения существующие тесты.

Цель: не тестировать сам код, а оценивать эффективность тестового покрытия. Хорошие тесты должны «убивать» мутации (т.е. падать), а выжившие мутации указывают на слабые места в тестах.

Как это работает (на примере):

  1. Исходный код:
    public int max(int a, int b) {
        if (a > b) {
            return a;
        }
        return b;
    }
  2. Мутант (изменение оператора > на >=):
    public int max(int a, int b) {
        if (a >= b) { // Мутация!
            return a;
        }
        return b;
    }
  3. Запускаются тесты. Если тест assertThat(max(5,5)).isEqualTo(5) отсутствует, мутант выживет (тесты пройдут), что покажет пробел в покрытии граничного случая (a == b).

Типы мутаций:

  • Изменение операторов: a > ba >= b, a + ba - b.
  • Изменение констант: return 0;return 1;.
  • Удаление вызовов методов: list.add(item); (ничего).
  • Изменение условий: if (cond)if (true) / if (false).

Инструменты для Java: PITest (Pitest) — наиболее популярный и практичный фреймворк. Интегрируется с Maven/Gradle и предоставляет детальный отчёт о выживших мутантах.

Преимущества:

  • Обнаруживает тесты, которые выполняют код, но не проверяют его логику (тесты-«пустышки»).
  • Побуждает писать более строгие и содержательные assertions.
  • Дополняет метрику coverage, которая показывает только выполнение строк, но не их проверку.

Недостатки: Вычислительно затратно, требует времени на анализ результатов.