Mutatsioonitestimine

**Mutatsioonitestimine** on üks testimise vorme, mille abil saab luua uusi tarkvarateste või hinnata olemasolevate testide kvaliteeti. Mutatsioonitestimine kaasab programmi lähtekoodi muutmist väikeste osade kaupa. 

Igat muudetud programmiosa nimetatakse mutandiks*,* mille toimel võib modifitseeritud programmi käitumine erineda esialgsest programmist*.* Mutandid põhinevad rangelt defineeritud mutatsioonioperaatorite põhjal, mis imiteerivad tüüpilisi programmeerimisvigu (näiteks kasutades väärasid aritmeetilisi operaatoreid) ning mille toimel avastatakse programmis veaohtlikke koodijuppe. Selliste muutuste avastamist olemasolevate testide poolt nimetatakse mutandi tapmiseks*.* Programmi testikomplekte saab hinnata selle põhjal, kui suure osa mutantidest antud testid ära tapavad. Selle kaudu saab luua uusi teste, et tappa mutante, mida algne testikomplekt ei avastanud. Mutatsioonitestimine on osa valge kasti meetodi tüüpidest.

## Ajalugu
Esialgse mutatsioonitestimisese idee pakkus välja Richard Lipton aastal 1971. Teooriat arendas ja selle avaldas Lipton koos Richard DeMillo ja Fred Saywardiga aastal 1978. Esimese mutatsioonitestimisetööriista lõi Timothy Budd aastal 1980 Yale'i ülikoolis.

## Ülevaade
Mutatsioonitestimisel on mitu eesmärki:

* tuvastada sellised koodiosad, mille korral mutante ära ei tapeta;
* tuvastada ebaefektiivsed ning ebavajalikud testid, mis ei tapa ühtegi mutanti;
* arvutada välja programmi testikomplekti headus tapetud mutantide ja mutantide koguarvu suhtena;
* uurida programmi vigade levikut mutantide lisamisel.

Mutatsioonitestimine põhineb kahel hüpoteesil. Esimene hüpotees on pädeva programmeerija hüpotees, mille kohaselt suurem osa kogenud programmeerija tarkvaras esinevatest vigastest tuleneb väiksematest süntaksivigadest. Teiseks hüpoteesiks on sidestamise mõju*,* mille kohaselt võib väiksemate vigade toimel koodis avalduda suuremad, seni teadmata vead.

Vähemärgatavatele vigadele saavad tähelepanu juhtida kõrgema järgu mutandid, mis toetavad samuti sidestamise mõju. Kõrgema järgu mutante saab kasutusele võtta luues mutante, millel on rohkem kui üks mutatsioon.

Mutatsioonitestimist sooritatakse lähtekoodi peal, võttes aluseks hulga mutatsioonioperaatoreid ning rakendades neid iga sobiva koodijupi peal.

Näiteks olgu programmil järgnev koodijupp:
```cpp
if (a && b) {
    c = 1;
} else {
    c = 0;
}
```
Antud koodijupi peal rakendatakse tingimuslikku mutatsioonioperaatorit, mille toimel asendatakse konjunktsioon `&&` disjunktsiooniga `||`. Tulemuseks tekib järgnev mutant:
```cpp
if (a || b) {
    c = 1;
} else {
    c = 0;
}
```

Programmi testikomplekt peaks antud mutandi tapmiseks täitma kolm tingimust:

# test peab jõudma muteerunud lauseni;
# testi sisendandmed peavad olema sellised, et algprogrammi ja muteerunud programmi vaheseisundid oleksid erinevad. Antud testi puhul sobivad sellisteks sisendandmeteks väärtused `a = 1` ja `b = 0`;
#algprogrammist erinev vaheseisund (muutuja `c` väärtus) peab kajastuma programmi väljundis ning olema testi poolt kontrollitud.

Antud tingimused moodustavad RIP (''Repeat-Induced Point)'' mudeli. Kasutades RIP-mudelit, saame eristada kahte mutatsioonitestimisliiki. Nõrgaks mutatsioonitestimiseks nimetatakse testimist, mis rahuldab RIP-mudeli esimesed kaks tingimust. Tugevaks mutatsioonitestimiseks nimetatakse testimist, mis rahuldab kõik kolm RIP-mudeli tingimust.

## Ekvivalentsed mutandid
Teatud mutantide korral ei ole võimalik luua sellist testikomplekti, mis suudaks antud mutandi ära tappa, kuna muteerunud programm oleks iga vaheseisundi korral sama käitumisega kui algne programm. Selliseid mutante nimetatakse ekvivalentseteks mutantideks.

Näiteks olgu antud järgmine koodijupp:
```c++
i = 0
while (true) {
    i++
    if (i == 5) break;
}
```
Ekvivalentne mutant tekiks näiteks siis, kui asendaksime operaatori `==` operaatoriga `>=` . Tulemuseks oleks kood kujul:
```c++
i = 0
while (true) {
    i++
    if (i >= 5) break;
}
```
Hoolimata sellest, et on muudetud tsükli lõpptingimuse kontrolli, lõpetab siiski programm töö alati samal juhul, kui esialgne programm. Seetõttu on mutant eristamatu algprogrammist. Ekvivalentsete mutantide leidmine, isegi väiksemate programmide puhul, on tihti ajakulukas erinevate seisundite ülevaatamise tõttu.

## Viited