Какво е мутационен тест? (Пример)
⚡ Умно обобщение
Тестването за мутации умишлено въвежда малки грешки в изходния код и след това изпълнява съществуващия набор от тестове срещу всяка дефектна версия, измервайки дали тези тестове са достатъчно силни, за да открият промяната.
Какво е мутационен тест?
Тестване на мутации е вид софтуерно тестване, при което определени твърдения от изходния код се променят или мутират, за да се провери дали тестовите случаи са в състояние да открият грешки в него. Целта на мутационното тестване е да се гарантира качеството на тестовите случаи по отношение на устойчивост, така че те да не се справят с мутиралия изходен код.
Промяната, направена в мутантна програма, трябва да бъде изключително малка, така че да не повлияе на общата цел на програмата. Тестването на мутации се нарича още стратегия за тестване, базирана на грешки, защото включва умишлено създаване на грешка в програмата. Това е форма на Бял Box Тестване което се прилага главно по време на Единично тестване.
Тестването на мутации е предложено през 1971 г. в студентска статия от Ричард Липтън и е формализирано в статията от 1978 г. „Съвети за избор на тестови данни“ от ДеМило, Липтън и Сейуърд. То губи инерция поради разходите за изчисления по онова време и оттогава си възвръща позициите за езици като Java, C#, Python, JavaСкрипт и XML.
Как да изпълним мутационен тест?
Следват стъпките за извършване на тестване за мутации, известно още като анализ на мутации:
Стъпка 1: Грешките се въвеждат в изходния код на програмата чрез създаване на много версии, наречени мутанти. Всеки мутант трябва да съдържа една грешка, а целта е да се предизвика неуспех на мутантна версия, което демонстрира ефективността на тестовите случаи.
Стъпка 2: Тестовите случаи се прилагат към оригиналната програма, а също и към мутантна програма. Тестов случай трябва да е адекватен и е променен, за да открива грешки в програмата.
Стъпка 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 релационен оператор или отрицание на условие.
Инструментите групират своите оператори под тези три заглавия, така че семейството, което е създало оцелял мутант, казва на тестващия какъв вид твърдение липсва. Оцелял мутант за решение обикновено маркира непроверен клон, който се припокрива с тестване на контур.
Автоматизиране на мутационния тест
Тестването за мутации е изключително времеемко и сложно за ръчно изпълнение, така че е препоръчително да се използват инструменти за автоматизация, които също така намаляват разходите. Инструментът за мутации компилира мутантите, планира тестовете, записва кой мутант е унищожил всеки неуспешен тест и докладва резултата.
Списък с налични инструменти:
- Stryker — рамка за тестване на мутации с отворен код с издания за JavaСценарий и TypeScript (StrykerJS), C# и .NET (Stryker.NET) и Scala (Stryker4s).
- PIT, наричана още PITest — система за тестване на мутации за Java и JVM, която мутира компилирания байткод и се включва в Maven и Gradle изгражда редом JUnit.
И двете се изпълняват като стъпка от изграждането, така че принадлежат към едно и също непрекъсната интеграция тръбопровода, както и останалата част от тестване за автоматизация нататък.
Мутационен резултат
Резултатът от мутациите се определя като процент на убити мутанти от общия брой мутанти.
Резултат на мутация = (Убити мутанти / Общ брой мутанти) * 100
Формулата е показана по-долу във вида, в който повечето инструменти я отчитат.
Тестовите случаи се описват като адекватни на мутацията, когато резултатът достигне 100 процента. На практика знаменателят трябва да изключва еквивалентни мутанти — мутанти, чийто променен синтаксис се държи точно като оригинала, така че никой тест не може да ги убие. Следователно инструментите отчитат убитите мутанти, разделени на убитите плюс оцелелите нееквивалентни мутанти, и позволяват на тестващия да маркира еквиваленти.
Експерименталните резултати показват, че тестването на мутации е ефективен начин за измерване на адекватността на тестовите случаи. Основният недостатък е цената на генерирането на мутантите и изпълнението на всеки тестов случай спрямо всеки един от тях.
Тестване за мутации срещу Code Обхват
Високо покритие на теста не доказва силни тестове. Покритието на редове и клонове записва кои оператори са изпълнени, а не дали нещо е било проверено след това, така че тест, който извиква метод и твърди, че нищо не е валидно, все още се счита за покрит. Тестването на мутации запълва тази празнина, защото мутантът умира само когато твърдение действително е неуспешно.
| Аспект | Code обхват | Резултат от мутации |
| Какво измерва | Кои линии или разклонения са изпълнени от тестовете | Кои инжектирани грешки са открити от тестовете |
| Чувствителен към твърдения | Не — тест с нула твърдения все пак добавя покритие | Да - мутант оцелява, когато никое твърдение не се провали |
| Цена на едно бягане | Едно инструментално тестово изпълнение | Един тестов цикъл на оцелял мутант, засега по-бавно |
| Типична употреба | Бърз достъп до всеки коммит | По-задълбочена периодична проверка на критичните модули |
| Режим на отказ | 100 процента покритие без реална проверка | Еквивалентни мутанти, които никога не могат да бъдат убити |
Двете метрики се допълват. Покритието посочва кода, който никога не е бил достигнат; резултатът от мутацията посочва достигнатия код, който никога не е бил проверен. И двете подават едни и същи данни. процес на управление на дефекти, наред с мерки като плътност на дефектите.
Предимства на мутационния тест
Следват предимствата на мутационния тест:
- Това е мощен подход за постигане на високо покритие на изходната програма.
- Той тества самия тестов набор, който никой друг не може да предложи. техника за тестване на софтуер прави директно.
- Тестването на мутации осигурява добро ниво на откриване на грешки на разработчика на софтуер.
- Методът разкрива неясноти в изходния код и има капацитета да разкрива грешки, до които обикновените изпълнения никога не достигат.
- Оцелелите мутанти подлежат на действие: всеки от тях назовава специфичен ред и специфична промяна, която екипът не е забелязал.
- Клиентите се възползват от това тестване, като получават по-надеждна и стабилна система.
Недостатъци на мутационния тест
От друга страна, недостатъците на тестването за мутации са следните:
- Тестването на мутации е изключително скъпо и отнема много време, защото трябва да се генерират и компилират голям брой мутантни програми.
- Тъй като отнема време, е редно да се каже, че това тестване не може да се извърши без инструмент за автоматизация.
- Всеки мутант се упражнява от същия брой тестови случаи като оригиналната програма, така че голяма популация от мутанти трябва да бъде изпълнена спрямо целия набор от тестове.
- Еквивалентните мутанти не могат да бъдат убити с никакъв тест и отделянето им от истински оцелелите обикновено изисква ръчен преглед.
- Тъй като методът променя изходния код, той не е приложим за черно Box Тестване.
Кога да се използва тестване за мутации
Горният профил на разходите означава, че тестването за мутации рядко се изпълнява върху цяла кодова база при всеки коммит. То се изплаща, когато неоткрита грешка е скъпа, а тестваният код е достатъчно малък, за да мутира бързо.
- Логика, критична за безопасността, или финансова логика — изчисляване на плащанията, данъчни правила и проверки на оторизациите, където един мълчалив грешен отговор е по-лош от катастрофа.
- Апартаменти с подозрително високо покритие — когато покритието е близо 100 процента, но все пак се наблюдават дефекти.
- Рефакторинг на остарял код — резултатите от мутациите показват дали съществуващите тестове биха довели до регресия.
- Библиотеки и споделени компоненти — дефект в повторно използван компонент умножава се за всеки обаждащ се.
- Трениращи отбори разработка, управлявана от тестове — резултатът проверява дали тестовете, написани първо, вършат реална работа.
Обикновено не си струва да се работи върху прототипи за еднократна употреба, върху „тънко лепило“ или генериран код без логика на разклоняване, или върху пакети, доминирани от бавни... интеграционни тестове които вече отнемат часове за едно преминаване.
Поради това повечето екипи обхватят изпълнението до променени файлове, задават праг за важните модули и позволяват на по-широкия регресионно тестване апартаментът носи останалата част от жизнен цикъл на софтуерно тестване.



