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

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

Вступление

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

Обзор

Тесты могут быть созданы для проверки правильности реализации данной программной системы, но создание тестов по-прежнему ставит вопрос, являются ли тесты правильными и достаточно ли они покрывают требования, которые послужили причиной реализации. (Эта технологическая проблема сама по себе является примером более глубокой философской проблемы под названием « Quis custodiet ipsos custodes? » [«Кто будет охранять охранников?»].) Идея состоит в том, что если мутант вводится, не будучи обнаруженным набором тестов, это означает, что либо измененный код никогда не выполнялся (мертвый код), либо набор тестов не смог обнаружить ошибки, представленные мутантом.

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

Цели

У тестирования мутаций несколько целей:

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

История

Тестирование мутаций было первоначально предложено Ричардом Липтоном, студентом в 1971 году, и впервые разработано и опубликовано ДеМилло, Липтоном и Сэйвордом. Первая реализация инструмента тестирования мутаций была осуществлена ​​Тимоти Баддом в рамках своей докторской работы (под названием « Анализ мутаций» ) в Йельском университете в 1980 году .

В последнее время, с появлением огромных вычислительных мощностей, в сообществе компьютерных наук возродился анализ мутаций, и была проделана работа по определению методов применения тестирования на мутации к объектно-ориентированным языкам программирования и непроцедурным языкам, таким как XML , SMV и конечные автоматы .

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

Нечеткость можно рассматривать как частный случай тестирования мутаций. При фаззинге сообщения или данные, которыми обмениваются внутри интерфейсов связи (как внутри, так и между экземплярами программного обеспечения), видоизменяются для выявления сбоев или различий в обработке данных. Codenomicon (2001) и Mu Dynamics (2005) развили концепции фаззинга до платформы тестирования мутаций с полным отслеживанием состояния, укомплектованной мониторами для тщательного тестирования реализаций протоколов.

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

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

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

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

Например, рассмотрим следующий фрагмент кода C ++:

if (a && b) {
    c = 1;
} else {
    c = 0;
}

Оператор мутации условия заменит && на || и произведет следующий мутант:

if (a || b) {
    c = 1;
} else {
    c = 0;
}

Теперь, чтобы испытать этот мутант, должны быть выполнены следующие три условия:

  1. Тест должен достичь измененного утверждения.
  2. Входные данные теста должны влиять на состояние программы, вызывая разные состояния программы для мутанта и исходной программы. Например, тест с a = 1 и b = 0 сделает это.
  3. Неправильное состояние программы (значение 'c') должно распространяться на выходные данные программы и проверяться тестом.

Эти условия в совокупности называются моделью RIP .

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

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

Обнаружение эквивалентных мутантов - одно из самых больших препятствий для практического использования мутационного тестирования. Усилия, необходимые для проверки эквивалентности мутантов, могут быть очень высокими даже для небольших программ. Систематический обзор литературы по широкому спектру подходов к преодолению проблемы эквивалентных мутантов выявил 17 соответствующих методов (в 22 статьях) и три категории методов: обнаружение (DEM); предлагая (SEM); и избежание эквивалентного поколения мутантов (AEMG). Эксперимент показал, что мутация высшего порядка в целом и стратегия JudyDiffOp в частности обеспечивают многообещающий подход к проблеме эквивалентных мутантов.

Операторы мутации

Исследователями были изучены многие операторы мутации. Вот несколько примеров операторов мутации для императивных языков:

  • Удаление выписки
  • Дублирование или вставка оператора, например goto fail;
  • Замена логических подвыражений на true и false
  • Замена одних арифметических операций другими, например, + на * , - на /
  • Замена одних логических отношений на другие, например, > на >= , == и <=
  • Замена переменных другими из той же области видимости (типы переменных должны быть совместимы)
  • Удалить тело метода, реализованное в Pitest

Эти операторы мутации также называются традиционными операторами мутации. Существуют также операторы мутации для объектно-ориентированных языков, для параллельных конструкций, сложных объектов, таких как контейнеры, и т. Д. Операторы для контейнеров называются операторами мутации уровня класса . Например, инструмент muJava предлагает различные операторы мутации на уровне класса, такие как изменение модификатора доступа, вставка оператора приведения типов и удаление оператора приведения типов. Операторы мутации также были разработаны для тестирования уязвимостей безопасности программ.

Смотрите также

Рекомендации