Что такое мутационное тестирование? (Пример)

⚡ Умное резюме

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

  • 🔘 Определение: Мутантная программа — это программа, в которой внесено одно преднамеренное синтаксическое изменение, и её удаление доказывает, что тест обнаружил это изменение.
  • ☑️ Процесс: Сгенерируйте мутанты, запустите набор тестов на исходном и мутантном вариантах, сравните результаты, а затем усильте тесты, которые пропустили ошибки.
  • OperaТорс: OperaЗамена генов, модификация экспрессии и модификация формулировок приводят к образованию трех основных семейств мутантов.
  • 🧪 Гол: Показатель мутаций — это процент убитых мутантов, и он измеряет силу убеждения, а не просто выполнение заданий.
  • 🇧🇷 оснастка: Чехлы Страйкера Javaсценарий, TypeScriptC# и Scala, в то время как PIT изменяет байт-код JVM внутри Maven и Gradle строит.
  • ⚠️ Стоимость: При каждом мутантном варианте тестируется весь набор тестов заново, поэтому мутационное тестирование — это медленный, дорогостоящий и непрактичный процесс без автоматизации.

Мутационное тестирование

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

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

Изменения, вносимые в мутантную программу, должны быть крайне незначительными, чтобы не повлиять на общую цель программы. Мутационное тестирование также называют стратегией тестирования на основе ошибок, поскольку оно предполагает преднамеренное создание ошибки в программе. Это одна из форм мутационного тестирования. Белый Box Тестирование что применяется главным образом во время Модульное тестирование.

Мутационное тестирование было предложено в 1971 году в студенческой работе Ричарда Липтона и формализовано в статье 1978 года «Советы по выбору тестовых данных» ДеМилло, Липтона и Сэйварда. Его развитие замедлилось из-за вычислительной стоимости того времени, но с тех пор оно вновь стало популярным в таких языках программирования, как... Java, С#, Python, JavaСкрипт и XML.

Как провести мутационное тестирование?

Ниже описаны шаги для проведения мутационного тестирования, также известного как мутационный анализ:

Шаг 1: В исходный код программы вносятся ошибки путем создания множества версий, называемых мутантами. Каждый мутант должен содержать одну ошибку, и цель состоит в том, чтобы вызвать сбой в мутантной версии, что демонстрирует эффективность тестовых примеров.

Шаг 2: Тестовые примеры применяются как к исходной программе, так и к мутантной программе. Тестовый кейс должен быть адекватным и настроен для обнаружения ошибок в программе.

Шаг 3: Сравните результаты исходной и модифицированной программы.

Шаг 4: Если исходная программа и мутантная программа выдают разные результаты, то мутантная программа уничтожается тестовым примером. Следовательно, тестовый пример достаточно хорош для обнаружения изменений между исходной и мутантной программами.

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

Схема ниже tracЭто те же пять этапов, от первоначальной программы и создания мутантов до вынесения вердикта о гибели или выживании.

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

Как создавать программы-мутанты?

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

Оригинальная программа Программа мутантов
Если (х>у)
Напечатать «Привет»
Еще
Напечатайте «Привет»
Если (x)
Напечатать «Привет»
Еще
Напечатайте «Привет»

В приведенной выше паре изменился только оператор сравнения, однако в тестовом случае, когда x больше y, теперь вместо «Hello» выводится «Hi». Иллюстрация демонстрирует это одно синтаксическое изменение.

Одно синтаксическое изменение, внесенное в оператор программы, приводит к созданию единственного мутанта.

Что изменить в программе-мутанте?

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

Operand операторы замены Операторы модификации выражений операторы модификации операторов
Замените операнд другим операндом (x на y или y на x) или константой. Заменить оператор или вставить новый оператор в операторе программы. Программные операторы модифицируются для создания мутантных программ.
Пример:
If(x>y) заменить значения x и y
Если (5>y) замените x на константу 5
Пример:
Если (х == у)
Мы можем заменить == на >= и получить программу-мутант следующего вида.
If(x>=y) и вставка ++ в оператор
Если(х==++у)
Пример:
Удалить часть else в операторе if-else
Удалите весь оператор if-else, чтобы проверить, как работает программа.

Примеры операторов мутации:

  • Замена метки GOTO
  • Замена оператора возврата
  • Удаление заявления
  • Вставка унарных операторов (например, – и ++)
  • Замена логического разъема
  • Сопоставимая замена имени массива
  • Удаление части else из оператора if-else
  • Добавление или замена операторов
  • Замена оператора путем изменения данных
  • Модификация данных для переменных
  • Модификация типов данных в программе

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

Типы мутационного тестирования

In Программная инженерияМутационное тестирование в основном подразделяется на три типа: мутация оператора, мутация значения и мутация решения.

  • Мутация заявления – оператор вырезается, вставляется или удаляется, поэтому результатом может быть удаление нескольких строк кода.
  • Мутация значения – Изменяются значения основных параметров и констант, например, изменяется граница цикла или пороговое значение.
  • Мутация решения – управляющие операторы изменяются, например, оператор flip.ping оператор сравнения или отрицание условия.

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

Автоматизация мутационного тестирования

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

Список доступных инструментов:

  • Stryker — фреймворк для мутационного тестирования с открытым исходным кодом, имеющий различные модификации для JavaСценарий и TypeScript (StrykerJS), C# и .NET (Stryker.NET), а также Scala (Stryker4s).
  • НДФЛтакже пишется как PITest — система мутационного тестирования для Java а также JVM, которая изменяет скомпилированный байт-код и интегрируется с Maven и Gradle строится вместе JUnit.

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

Оценка мутаций

Показатель мутаций определяется как процент погибших мутантов от общего числа мутантов.

Оценка мутации = (Убитые мутанты / Общее количество мутантов) * 100

Формула представлена ​​ниже в том виде, в котором её отображает большинство инструментов.

Формула оценки мутаций: деление числа погибших мутантов на общее число мутантов и умножение на сто.

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

Результаты экспериментов показали, что мутационное тестирование является эффективным способом оценки адекватности тестовых примеров. Главный недостаток заключается в стоимости генерации мутантов и выполнения каждого тестового примера для каждого из них.

Тестирование на мутации против Code Покрытие

Высокий тестовое покрытие Это не доказывает надежность тестов. Покрытие строк и ветвей фиксирует, какие операторы были выполнены, а не было ли что-либо проверено после этого, поэтому тест, который вызывает метод и ничего не утверждает, все равно считается покрытым. Мутационное тестирование устраняет этот пробел, поскольку мутант умирает только тогда, когда утверждение действительно не выполняется.

Аспект Code охват Оценка мутации
Что он измеряет Какие строки или ветви были выполнены тестами? Какие именно ошибки были обнаружены в ходе тестирования?
Чувствителен к утверждениям Нет — тест без утверждений всё равно добавляет покрытие кода. Да — мутант выживает, если ни одно утверждение не терпит неудачу.
Стоимость пробега Один тестовый запуск с использованием измерительных приборов Один тестовый запуск на каждого выжившего мутанта, поэтому гораздо медленнее.
Типичное использование Быстрый контроль на каждом коммите Более тщательная периодическая проверка критически важных модулей.
Режим отказа 100-процентное покрытие без реальной проверки Эквивалентные мутанты, которых невозможно убить.

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

Преимущества мутационного тестирования

Ниже приведены преимущества мутационного тестирования:

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

Недостатки мутационного тестирования

С другой стороны, к недостаткам мутационного тестирования относятся следующие:

  • Мутационное тестирование — чрезвычайно дорогостоящий и трудоемкий процесс, поскольку необходимо сгенерировать и скомпилировать большое количество мутантных программ.
  • Поскольку это трудоемкий процесс, справедливо будет сказать, что такое тестирование невозможно провести без инструмента автоматизации.
  • Каждый мутант проверяется таким же количеством тестовых случаев, как и исходная программа, поэтому для проверки всего набора тестов необходимо использовать большую популяцию мутантов.
  • Эквивалентных мутантов невозможно уничтожить никакими тестами, и для их отделения от подлинных выживших обычно требуется ручная проверка.
  • Поскольку этот метод изменяет исходный код, он неприменим к Цвет - Черный. Box Тестирование.

Когда следует использовать мутационное тестирование?

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

  • Критически важная с точки зрения безопасности или финансовая логика — расчет платежей, налоговые правила и проверки авторизации, где молчаливый неправильный ответ хуже, чем авария.
  • Номера с подозрительно высоким уровнем покрытия — когда показатель покрытия близок к 100 процентам, но дефекты всё же остаются незамеченными.
  • Устаревший код подвергается рефакторингу. — Результаты мутаций показывают, смогут ли существующие тесты выявить регрессию.
  • Библиотеки и компоненты общего пользования — дефект в повторно используемом компонент Умножается на каждого звонящего.
  • Тренировки команд разработка через тестирование — Этот результат проверяет, действительно ли написанные тесты выполняют реальную работу.

Как правило, не стоит запускать его на одноразовых прототипах, на коде с поверхностным связем или сгенерированном коде без логики ветвления, а также на тестовых наборах, в которых преобладают медленные процессы. интеграционные тесты На один заезд и так уходит несколько часов.

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

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

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

Универсального показателя не существует. Команды обычно устанавливают высокий порог для критически важных модулей, таких как модули оплаты или логики безопасности, и более низкий для остальных. Погоня за процентом менее полезна, чем проверка каждого оставшегося «мутанта» в коде высокого риска.

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

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

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

Да, что касается механической части. Имея в наличии выживший мутант и тестируемый метод, Copilot составляет недостающее утверждение или тест для граничного случая. Рецензент все равно должен подтвердить, что ожидаемое значение корректно и не просто скопировано из текущего поведения.

Это позволяет проверить результат. Разработка через тестирование создает тесты до написания кода, но ничто не гарантирует, что эти тесты содержат достаточно утверждений. Периодическое обновление одних и тех же модулей показывает, действительно ли цикл «красный-зеленый» привел к созданию тестов, которые не проходят при неправильном ответе.

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

Подведем итог этой публикации следующим образом: