Що таке мутаційний тест? (Приклад)

⚡ Розумний підсумок

Тестування мутацій навмисно вносить невеликі помилки у вихідний код, а потім запускає існуючий набір тестів для кожної версії з дефектом, вимірюючи, чи достатньо сильні ці тести, щоб виявити зміни.

  • 🔘 Визначення: Мутант — це програма, яка несе одну навмисну ​​синтаксичну зміну, і її знищення доводить, що тест виявив цю зміну.
  • ☑️ Процес: Створіть мутанти, запустіть набір тестів для порівняння з оригіналом та мутантом, порівняйте результати, а потім підсиліть тести, які пропустили помилки.
  • Operaторс: OperaЗаміна, модифікація експресії та модифікація оператора утворюють три основні родини мутантів.
  • 🧪 Оцінка: Оцінка мутації – це відсоток знищених мутантів, і вона вимірює силу твердження, а не просто виконання рядка.
  • 🛠️ інструменти: Чохли Stryker Javaсценарій, TypeScript, C# та Scala, тоді як PIT змінює байт-код JVM всередині Maven та Gradle будує
  • ⚠️ Вартість: Кожен мутант повторно запускає весь набір, тому тестування мутацій є повільним, дорогим та непрактичним без автоматизації.

Тестування мутацій

Що таке мутаційний тест?

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

Зміна, внесена в мутантну програму, має бути надзвичайно малою, щоб вона не вплинула на загальну мету програми. Тестування на мутації також називають стратегією тестування на основі помилок, оскільки воно передбачає навмисне створення помилки в програмі. Це форма білий Box Тестування що застосовується переважно під час Unit Testing.

Тестування мутацій було запропоновано в 1971 році в студентській статті Річарда Ліптона та формалізовано в статті 1978 року «Підказки щодо вибору тестових даних» ДеМілло, Ліптона та Сейворда. Воно втратило імпульс через вартість обчислень того часу та з того часу знову набуло популярності для таких мов, як Java, C#, Python, JavaСкрипт та XML.

Як провести мутаційний тест?

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

Крок 1: Помилки вводяться у вихідний код програми шляхом створення багатьох версій, які називаються мутантами. Кожен мутант повинен містити одну помилку, а метою є те, щоб мутантна версія зазнала невдачі, що демонструє ефективність тестових випадків.

Крок 2: Тестові випадки застосовуються до оригінальної програми, а також до програми-мутанта. A Тестовий випадок має бути адекватним, і його налаштовано для виявлення помилок у програмі.

Крок 3: Порівняйте результати оригінальної та мутантної програм.

Крок 4: Якщо оригінальна програма та програма-мутант генерують різні результати, то тестовий випадок знищує мутант. Отже, тестовий випадок достатньо хороший, щоб виявити різницю між оригінальною програмою та програмою-мутантом.

Крок 5: Якщо оригінальна програма та програма-мутант генерують однаковий результат, мутант залишається живим. У таких випадках необхідно створити ефективніші тестові випадки, які знищують усіх мутантів.

Діаграма нижче tracті ж самі п'ять кроків, від початкової програми через покоління мутантів до вироку про вбивство або виживання.

Робочий процес тестування мутацій, що показує оригінальну програму, згенеровані мутанти, виконання тесту та вердикт про вбитих або живих мутантів

Як створювати програми-мутанти?

Мутація — це не що інше, як одинична синтаксична зміна, внесена до оператора програми. Кожна програма-мутант повинна відрізнятися від оригінальної програми рівно на одну мутацію.

Оригінальна програма Програма Мутант
Якщо (x>y)
Надрукувати «Привіт»
Ще
Надрукувати «Привіт»
Якщо (x
Надрукувати «Привіт»
Ще
Надрукувати «Привіт»

У парі вище змінився лише оператор порівняння, проте тестовий випадок, де x більше за y, тепер друкує «Hi» замість «Hello». На ілюстрації показано це одне синтаксичне редагування.

Одна синтаксична зміна, застосована до оператора програми, для створення одного мутанта

Що змінити в програмі Mutant?

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

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

Деякі оператори мутації зразків:

  • Заміна етикетки GOTO
  • Заміна заяви про повернення
  • Видалення заяви
  • Вставка унарних операторів (таких як – та ++)
  • Логічна заміна роз'єму
  • Заміна імен порівняльного масиву
  • Видалення частини else з оператора if-else
  • Додавання або заміна операторів
  • Заміна заяви шляхом зміни даних
  • Модифікація даних для змінних
  • Модифікація типів даних у програмі

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

Види тестування на мутації

In Розробка програмного забезпеченняТестування мутацій принципово класифікується на три типи: мутація тверджень, мутація значень та мутація рішень.

  • Мутація заяви – оператор вирізається, вставляється або видаляється, тому результатом може бути видалення деяких рядків коду.
  • Мутація значення – значення первинних параметрів і констант змінюються, наприклад, змінюються межа циклу або поріг.
  • Мутація рішення – змінюються керуючі оператори, наприклад, flipping реляційний оператор або заперечення умови.

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

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

Тестування мутацій є надзвичайно трудомістким та складним для виконання вручну, тому доцільно використовувати інструменти автоматизації, які також знижують витрати. Інструмент для мутацій компілює мутанти, планує прогони, записує, який мутант знищив кожен невдалий тест, і повідомляє про результат.

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

  • Страйкер — фреймворк для тестування мутацій з відкритим кодом та версіями для JavaСценарій і TypeScript (StrykerJS), C# та .NET (Stryker.NET), а також Scala (Stryker4s).
  • PIT, також відома як PITest — система тестування мутацій для Java і JVM, яка змінює скомпільований байт-код та підключається до Maven, Gradle будує поруч JUnit.

Обидва виконуються як крок збірки, тому вони належать до одного безперервна інтеграція трубопровід, як і решта тестування автоматизації на.

Оцінка мутації

Оцінка мутації визначається як відсоток убитих мутантів від загальної кількості мутантів.

Показник мутації = (убиті мутанти / загальна кількість мутантів) * 100

Формула наведена нижче у формі, в якій її повідомляє більшість інструментів.

Формула для оцінки мутацій: кількість убитих мутантів ділиться на загальну кількість мутантів і множиться на сто.

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

Експериментальні результати показали, що тестування мутацій є ефективним способом оцінки адекватності тестових випадків. Основним недоліком є ​​вартість створення мутантів та виконання кожного тестового випадку для кожного з них.

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

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

Аспект Code охоплення Оцінка мутацій
Що він вимірює Які лінії або гілки виконували тести Які впроваджені несправності виявили тести
Чутливий до тверджень Ні — тест з нульовими твердженнями все одно додає покриття Так — мутант виживає, коли жодне твердження не зазнає невдачі
Вартість одного пробігу Один інструментальний тестовий прогін Один тестовий запуск на кожного мутанта, що вижив, поки що набагато повільніше
Типове використання Швидкий доступ до кожного коміту Глибша періодична перевірка критичних модулів
Режим відмови 100-відсоткове покриття без реальної перевірки Еквівалентні мутанти, яких ніколи не можна вбити

Ці дві метрики доповнюють одна одну. Покриття вказує на код, який ніколи не був досягнуто; показник мутації вказує на досягнутий код, який ніколи не перевірявся. Обидві метрики подають однакові дані. процес управління дефектами, поряд із такими заходами, як щільність дефектів.

Переваги тестування на мутації

Переваги мутаційного тестування:

  • Це потужний підхід для досягнення високого охоплення вихідної програми.
  • Він тестує сам набір тестів, чого не може зробити жоден інший методика тестування програмного забезпечення робить безпосередньо.
  • Тестування мутацій забезпечує розробнику програмного забезпечення хороший рівень виявлення помилок.
  • Цей метод виявляє неоднозначності у вихідному коді та має здатність виявляти помилки, до яких звичайні запуску ніколи не доходять.
  • Мутанти, що вижили, можуть бути піддані дії: кожен з них називає певний рядок і конкретну зміну, яку свита не помітила.
  • Клієнти отримують вигоду від цього тестування, отримуючи надійнішу та стабільнішу систему.

Недоліки тестування на мутації

З іншого боку, недоліки тестування на мутації такі:

  • Тестування мутацій є надзвичайно дорогим та трудомістким процесом, оскільки необхідно згенерувати та скомпілювати велику кількість мутантних програм.
  • Оскільки це займає багато часу, справедливо буде сказати, що це тестування неможливо виконати без інструменту автоматизації.
  • Кожен мутант перевіряється такою ж кількістю тестових випадків, як і оригінальна програма, тому велику популяцію мутантів необхідно протестувати на всьому наборі тестів.
  • Еквівалентних мутантів неможливо вбити жодним тестом, і їх відокремлення від справжніх вижили зазвичай потребує ручної перевірки.
  • Оскільки метод змінює вихідний код, він не застосовується до Black Box Тестування.

Коли використовувати тестування на мутації

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

  • Логіка, критично важлива для безпеки, або фінансова логіка — розрахунок платежів, податкові правила та перевірки авторизації, де мовчазна неправильна відповідь гірша за аварію.
  • Номери з підозріло високим покриттям — коли покриття близьке до 100 відсотків, але дефекти все одно не виявляються.
  • Рефакторинг застарілого коду — результати мутацій показують, чи виявлять існуючі тести регресію.
  • Бібліотеки та спільні компоненти — несправність у повторно використаному компонент множиться на кожного абонента.
  • Команди тренуються тестова розробка — оцінка перевіряє, чи тести, написані першими, дійсно працюють.

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

Тому більшість команд охоплюють змінені файли, встановлюють поріг для важливих модулів і дозволяють ширшому регресійне тестування люкс переносить решту життєвий цикл тестування ПЗ.

Поширені запитання

Еквівалентний мутант — це зміна, яка змінює синтаксис, але не поведінку, наприклад, заміна межі циклу, яка ніколи не досягається. Жоден тест не може його знищити, тому його потрібно позначити та виключити, перш ніж оцінка буде вважатися достовірною.

Немає універсального числа. Команди зазвичай встановлюють високий поріг для критичних модулів, таких як логіка оплати або безпеки, та нижчий для інших. Переслідування певного відсотка менш корисне, ніж перевірка кожного мутанта, що вижив, у коді з високим рівнем ризику.

Це два припущення, на яких базується ця методика. Перше стверджує, що програмісти пишуть майже правильний код, тому справжні помилки невеликі. Друге стверджує, що тести, які виявляють невеликі помилки, також виявляють складні помилки, побудовані на їх основі.

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

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

Так, для механічної частини. Враховуючи мутанта, що вижив, та метод, що тестується, Copilot складає чернетку відсутнього твердження або тесту на граничний випадок. Рецензент все одно має підтвердити, що очікуване значення є правильним, а не просто скопійованим з поточної поведінки.

Він перевіряє результат. Розробка на основі тестування створює тести перед кодом, але ніщо не гарантує, що ці тести мають достатню кількість стверджень. Періодична мутація, що виконується на тих самих модулях, показує, чи червоно-зелений цикл створив тести, які дійсно не дають результатів через неправильну відповідь.

Ні. Впровадження помилок пошкоджує середовище виконання та нечітке тестування подає невірні вхідні дані, оцінюючи застосунок. Тестування мутацій змінює вихідний код та оцінює набір тестів, тому об'єкт, що оцінюється, відрізняється.

Підсумуйте цей пост за допомогою: