Skip to content
IRC-CodingIRC-Coding
Mutation TestingMutation ScoreКачество тестовCode CoverageUnit TestsPITStryker

Mutation Testing: Насколько хороши твои тесты?

Изучи Mutation Testing: мутанты, Mutation Score, ограничения и инструменты. Оценивай качество тестов за пределами покрытия кода.

S

schutzgeist

4 min read
Mutation Testing: Насколько хороши твои тесты?

Mutation Testing

Code Coverage показывает, какой процент кода выполняется тестами. Однако он не говорит о том, действительно ли тесты проверяют этот код на ошибки. Mutation Testing закрывает этот пробел, внося небольшие изменения в исходный код и проверяя, обнаруживают ли их тесты. Если мутация, то есть искусственно внесённый дефект, пережила тестовый запуск, это значит, что тест недостаточно эффективен.

In a Nutshell

  • Mutation Testing вносит искусственные ошибки в исходный код.
  • Цель состоит в измерении качества тестов, а не только их покрытия.
  • Mutation Score = убитые мутанты / всего мутантов.
  • Высокая вычислительная нагрузка — главная сложность.

Компактное описание

При Mutation Testing создаются мутанты, то есть слегка изменённые версии production кода. Мутант может, например, изменить арифметический оператор, инвертировать условие или подменить возвращаемое значение. Test suite запускается для каждого мутанта. Если хотя бы один тест падает, мутант считается убитым. Если все тесты проходят, мутант выжил, что указывает на слабость тестов.

Mutation Score

Mutation Score вычисляется так:

Mutation Score = (Убитые мутанты / Всего мутантов) * 100

Высокий показатель означает, что тесты надёжно обнаруживают ошибки в коде. Низкий показатель говорит о том, что тесты выполняются, но не производят эффективную проверку.

Виды мутаций

Арифметические операторы

int result = a + b;  // Мутант: a - b

Операторы сравнения

if (x > 10) { ... }  // Мутант: x < 10

Возвращаемые значения

return true;  // Мутант: return false;

Удаление инструкций

System.out.println("log");  // Мутант: строка удалена

Условия

if (a && b)  // Мутант: if (a || b)

Основные инструменты

  • PIT: Mutation Testing для Java и JVM-языков.
  • Stryker: Mutation Testing для JavaScript, TypeScript и C#.
  • MutPy: Mutation Testing для Python.
  • Cosmic Ray: Mutation Testing для Python.
  • Infection: Mutation Testing для PHP.

Практический пример: простая мутация в Java

public class DiscountCalculator {
    public int calculate(int amount) {
        if (amount > 100) {
            return amount - 10;
        }
        return amount;
    }
}
@Test
public void testDiscountForLargeAmount() {
    DiscountCalculator calc = new DiscountCalculator();
    assertEquals(90, calc.calculate(100));  // Проблема: граничное значение 100 вместо 101
}

Мутант изменяет amount > 100 на amount >= 100. Для входного значения 100 в обоих случаях результат 90. Тест не обнаруживает мутанта, хотя условие различается. Это показывает, что тест неправильно проверяет граничное значение.

Достоинства и недостатки

Достоинства

  • Лучшее качество тестов: измеряет, действительно ли тесты проверяют что-то.
  • Меньше ложных срабатываний покрытия: сама по себе покрытие не доказывает качество.
  • Фокус на критических участках: слабые тесты становятся видны.
  • Лучшие тестовые случаи: разработчики вынуждены писать более содержательные assertion’ы.

Недостатки

  • Высокая вычислительная нагрузка: много мутантов требуют много тестовых запусков.
  • Эквивалентные мутанты: некоторые мутации не меняют поведение, но не могут быть автоматически обнаружены.
  • Длительное время выполнения: в больших проектах Mutation Testing может занимать часы.
  • Поддержка: при изменении кода мутанты нужно пересоздавать.

Ключевые моменты для подготовки

  • Определение и назначение Mutation Testing.
  • Mutation Score и его расчёт.
  • Виды мутаций.
  • Инструменты вроде PIT, Stryker, MutPy.
  • Разница между Coverage и Mutation Testing.
  • Проблемы с эквивалентными мутантами.

Типичные экзаменационные вопросы (с кратким ответом)

  1. Что такое Mutation Testing? Метод, который внедряет искусственные ошибки в код для измерения качества тестов.

  2. Что показывает Mutation Score? Долю мутантов, которые обнаружены и убиты тестами.

  3. Что такое эквивалентный мутант? Мутация, которая не меняет поведение программы, но всё равно не убивается тестом.

  4. Назови инструмент для Mutation Testing. PIT, Stryker, MutPy или Infection.

  5. В чём разница между Coverage и Mutation Testing? Coverage измеряет, какой код выполняется. Mutation Testing проверяет, обнаруживают ли тесты реальные ошибки.

Основные источники

  1. https://pitest.org
  2. https://stryker-mutator.io
  3. https://en.wikipedia.org/wiki/Mutation_testing

Часто задаваемые вопросы

Что такое мутант?

Мутант — это слегка изменённая версия исходного кода, которая представляет искусственную ошибку.

Что означает убитый мутант?

Мутант убит, когда после внесённого изменения падает хотя бы один тест. Это показывает, что тест обнаружил ошибку.

Какой Mutation Score считается хорошим?

Показатель выше 80 процентов часто рассматривается как хороший. Но важнее, чтобы тесты обнаруживали действительно критические ошибки.

Почему Mutation Testing требует большие вычисления?

Для каждого мутанта вся test suite должна запуститься снова. При большом количестве мутантов и большой кодовой базе это требует огромного времени.

Что такое эквивалентные мутанты?

Эквивалентные мутанты изменяют код, но не меняют поведение. Их нельзя автоматически обнаружить, и они искажают Mutation Score.

Mutation Testing подходит только для unit тестов?

В основном да, потому что unit тесты изолированы и быстры. Для integration тестов Mutation Testing менее распространено из-за времени выполнения и сложности.

Когда стоит применять Mutation Testing?

Имеет смысл в стабильных, критичных участках кода, когда покрытие уже высоко, но качество тестов остаётся неясным.

Какой типичный anti-pattern при Mutation Testing?

Написание тестов с assertion’ами, которые чересчур терпимы к почти любым изменениям, потому что они слишком обобщённые или слабые.

Может ли Mutation Testing работать в CI/CD pipeline?

Да, но из-за времени выполнения его часто запускают отдельно как ночную или еженедельную работу, а не при каждом commit’е.

Что такое Stryker?

Stryker — популярный фреймворк для Mutation Testing для JavaScript, TypeScript и C#.

Что такое PIT?

PIT — широко используемый инструмент для Mutation Testing для Java и других языков на основе JVM.

Заменяет ли Mutation Testing Code Coverage?

Нет. Он дополняет Coverage, измеряя содержательность тестов. Вместе обе метрики дают более полную картину.

Что означает Mutation Operator?

Mutation Operator — это правило, которое описывает, как изменяется код при создании мутанта, например инверсия оператора сравнения.

Как сократить время выполнения Mutation Testing?

Параллельное выполнение, инкрементальное Mutation Testing, фокус на критичные участки кода и исключение тривиальных или сгенерированных файлов.

О чём говорит выживший мутант?

Выживший мутант показывает, что test suite не обнаружила внесённую ошибку. Тест слишком слаб или проверяет неправильное поведение.

Далее в пути обучения Software Testing

Следующая статья пути Software Testing посвящена Shift-Left Testing — как размещать тесты раньше в процессе разработки.

Назад к блогу
Share:

Nächster Artikel in Качество программного обеспечения

Weiterlesen
Основы E2E тестирования: валидация пользовательских сценариев

Похожие статьи