При мутационном тестировании вносятся определенные изменения в программное обеспечение, если набор тестов их не находит — тогда приходится сделать вывод, что тестирование недостаточно эффективно. Другими словами, эффективность набора тестов определяется с помощью отдельных отклонений в ПО.

Звучит не очень понятно, не так ли? Рассмотрим пример.

Мутационное тестирование - демонстрируем простой пример

Допустим, существует сайт клиники, где пациенты проходят регистрацию. Система считывает дату рождения или возраст клиента. Для людей старше 14 назначается доктор для взрослых. Для этого активируется функция «общего доктора», которая подбирает свободного специалиста. Может присутствовать и другой функционал. Пациентам младше 13 назначается педиатр и т.д. Рассмотрим пример с детьми старше 14.

Код может выглядеть следующим образом:

1) Считывается возраст

2) Если возраст >14

3) Доктор = Общий доктор ()

4) И если

Примечание. Вышеперечисленные данные не являются линиями какого-либо языка программирования. Они нужны для наглядности.

Для условного теста используется произвольные данные: 14, 15, 0, 13. Цель в том, чтобы проверить, позволяет ли набор данных из четырех значений (14, 15, 0 и 3) обнаружить всевозможные проблемы, используя этот кода.

Как это делается с помощью мутационного тестирования?

Во-первых, создаются мутанты — вариации программы. Мутант — это просто программа, написанная со случайными изменениями, преднамеренными ошибками.

Примеры:

  • Замена символа, обозначающего арифметическую операцию
  • Замена логического соединителя
  • Удаление предложения
  • Замена оператора отношения
  • Ввод абсолютного значения

Эти замены еще называют «мутационными операторами».

Рассмотрим еще несколько примеров:

Мутант #1: Замена оператора отношения

1) Чтение возраста

2) Если возраст <14 ‘замена > на <’

3) Доктор = Общий врач ()

4) И если

Мутант #2:

1) Чтение возраста

2) Если возраст =14 ‘замена > на =’

3) Доктор = Общий врач ()

4) И если

Мутант #3:

1) Чтение возраста

2) Если возраст>=14 ‘замена > на >=’

3) Доктор = Общий врач ()

4) И если

Мутант #4:

1) Чтение возраста

2) Если возраст<=14 ‘замена > на <=’

3)Доктор = Общий врач ()

4) И если

Мутант#5

1) Чтение возраста

2) Если возраст=

3) ‘удалить назначение врача’

4) И если

Мутант #6: Ввод абсолютного значения

1) Чтение возраста

2) Если возраст>14

3) Доктор= X (Ввод абсолютного значения — допустим X — это врач-педиатр)

4) И если

Мутант #7: Некорректный синтаксис

1) Чтение возраста

2) Если возраст%%14 (некорректный синтаксис)

3) Доктор= Общий врач ()

4) И если

Мутант #8: Выполняет то же, что и оригинальный тест

1) Чтение возраста

2) Если возраст > 14 и возраст>14 ‘значит то же, что>14’

3) Доктор= Общий врач ()

4) И если

После создания мутантов, к ним применяется набор данных. В данном случае это 14, 15, 0 и 13. Какие из этих мутантов сможет обнаружить наш набор данных?

Таблица набора данных

Как можно видеть, значение данных 14 обнаруживает ошибки при применении мутантов 2, 3 и 4. Эти мутанты считаются «убитыми». Но набор окажется неэффективным применительно к 1, 6 и 8.

Если набор данных убивает всех мутантов, тогда его следует считать эффективным. Если нет, понадобится больше данных или более качественные данные. Нет необходимости в том, чтобы каждое значение в наборе данных убивало всех мутантов. Но по совокупности фрагменты исходного кода программы должны убивать всех мутантов. Например, 14 убивает 2, 3 и 4. 15 убивает 1, 2 и 4 и т.д.

Как насчет 5, 7 и 8?

Мутант #5 — это пример, который упадет, независимо от значения данных. Причина — он не выполняет никаких программных операций как для действительных, так и недействительных значений.

Мутант #7 — будет ошибкой. Или, в случае со скриптовым языком, ошибкой, которая не позволит выполнение программного кода.

Мутант #8 — То же, что и основная программа.

Как можно видеть, вышеперечисленные мутанты совершенно бесполезны.

Вот мутанты, которых следует избегать:

  • Синтаксически некорректные: нужны только корректные в синтаксическом отношении мутанты. Пример: мутант 7.
  • Эквивалентные мутанты: Такие, которые в точности повторяют исходную программу. Пример: мутант 8.
  • Тривиальные мутанты: мутанты, которые убиваются любым набором данных. Пример: мутант 5.

Особенности мутационного тестирования:

Общее число мутантов может быть сравнительно большим, даже для небольшой программы. Это конечное число, но все же довольно большое. По этой причине обычно применяется подмножество мутантов, которые используются совершенно произвольно — такая практика широко распространена.

Список перечисленных в этой статье мутационных операторов не исчерпывающий, допустимы и другие вариации. Мы лишь упростили общую идею, чтобы было понятнее.

Мутационные операторы отличаются в зависимости от языка программирования, дизайна и специфики конкретного приложения.

Если по завершении теста некоторые мутанты «выжили», тогда одно из двух: либо мутанты оказались совершенно бесполезными (5, 7 и 8), либо набор данных был неподходящим.

Мутационное тестирование структурно, как метод черного ящика или функциональное тестирование. Для генерации мутантов специально вводятся ошибки.

Существует множество фреймворков тестирования и инструментов для автоматизации мутационного теста. Вот несколько из них:

  • Jester для JUnit.
  • Pester для Python
  • MuClipse для eclipse, и т.д.

В основе мутационного тестирования — две составляющие:

  • Во-первых, программист должен быть достаточно компетентным. Если программисту по силам написать и протестировать небольшую часть кода, он сможет написать и более масштабные программы.
  • Во-вторых, если два элемента добавляются в программу, и каждый из них представляет определенную ценность, тогда это хорошая комбинация.