Liigu peamise sisu juurde

Sissejuhatus testimisse

Sissejuhatus

Kõik programmid on loodud eelduste põhjal, näiteks sisend peab saabuma mingis kindlas vormis, kindlad arvutused annavad kindla tulemuse ning et erijuhtumitega tegeletakse sujuvalt. Tarkvaraarenduses on testimine praktika, mille käigus kontrollitakse süstemaatiliselt, kas need eeldused reaalsuses ka paika peavad.

Ilma testideta on ainus viis selles kindel olla programmi käivitades ja käsitsi kontrollides. Selline lähenemine on sobilik kergemate rakenduste puhul (mis koosnevad ainult paarist koodireast), kuid tegelikuses väga ebapraktiline. Automaattestid talletavad neid kontrolle koodina, et neid saaks koheselt ja usaldusväärselt korduvalt teostada.

Testimise tähtsus

Testimisel on mitu eesmärki, mis ei piirdu ainult vigade avastamisega.

Vigade varajane avastamine. Arenduse käigus avastatud viga on odavam parandada kui tootmiskeskkonnas leitud viga. Testid toimivad varajase hoiatuse süsteemina, mis märgib probleemid kohe, kui need tekivad.

Regressioonide vältimine. Töötav kood võib katki minna, kui süsteemi teisi osi muudetakse. Testid tuvastavad need regressioonid automaatselt. Kui midagi läks katki, siis see ilmneb koheselt selle juhtumisel, mitte alles siis, kui rakenduse kasutaja sellest teatab.

Tagab muudatuste tegemiseks enesekindluse. Koodi refaktoreerimine, uue funktsionaalsuse lisamine või sõltuvuste uuendamine on kõik kõrge riskiga tegevused. Tugev testikomplekt annab kindluse, et olemasolev käitumine säilib ka pärast muudatusi. Ilma testideta kipuvad arendajad vältima töötava koodi muutmist, mis viib stagnatsioonini.

Testid dokumenteerivad koodi. Testid toovad konkreetseid näiteid selle kohta, kuidas mõni meetod peaks käituma. Olgu siis selleks, mis sisendeid see vastu võtab, mis tulemuseks annab ning kuidas erijuhtumeid käsitletakse. Erinevalt kommentaaridest on testid käivitatavad. Need ei saa aeguda ilma, et need läbi kukuksid.

Näide ühest testist:

@Test
void testDepositIncreasesBalance() {
Account account = new Account(100.0);

account.deposit(50.0);

assertEquals(150.0, account.getBalance());
}

Sellest testist saame välja lugeda, mis juhtub kui välja kutsuda deposit meetodit ilma et peaksime klassi avama ja sinna lugema minema.

Tagab paremat koodidisaini. Kood, mida on raske testida, viitab tavaliselt disainiprobleemile: liiga palju vastutusi, peidetud sõltuvused või liigne sidusus. Testide kirjutamine soodustab väiksemaid meetodeid selgete sisendite ja väljunditega, mis muudab koodi arusaadavamaks ja lihtsamini hooldatavaks. Kui mingi koodilõigu testimiseks on vaja keerukat ettevalmistust, siis seda koodi on tõenäoliselt raske kasutada ka kasutajatel.


Tüüpiliselt keskenduvad arendajad sellele, et kood töötaks ettenähtud kasutusjuhu puhul. Seda nimetatakse happy path-iks. Funktsionaalsus töötab, oodatud sisendid annavad oodatud väljundid ning ülesanne tundub tehtud olevat.

Tarkvaratestija paneb selle mõtteviisi proovile. Testija küsib: mis juhtub tühja sisendi korral? Negatiivsete arvudega? null-iga? Väga suurte väärtustega? Mis siis, kui sama operatsiooni kutsutakse kaks korda? Mis siis, kui võrk on aeglane?

Head testid katavad nii ettenähtud kasutusjuhtu kui ka erijuhtumeid. Eesmärk on lõpuks kirjutada lisaks toimivale koodile ka vastupidavat koodi.

Erinevad testimistüübid

Üksustestid (unit tests) kontrollivad üksikuid meetodeid või klasse teistest sõltumatult. Need on kiired, fokusseeritud ja moodustavad testikomplekti aluse. Üksustest kutsub tavaliselt välja ühe meetodi etteantud sisenditega ning kontrollib saadud väljundit.

Integratsioonitestid (integration tests) kontrollivad, et mitu komponenti töötavad koos õigesti. Näiteks testitakse, et teenusekiht kutsub korrektselt välja andmekihi (repository) ja töötleb saadud tulemusi õigesti.

Läbivtestid (end-to-end tests) kontrollivad terviklikke kasutusjuhte läbi kogu süsteemi. Näiteks testitakse, et kasutaja saab süsteemi sisse logida, esitada tellimuse ja saada selle kohta kinnituse.

Iga tase on kompromiss kiiruse ja realistlikkuse vahel. Üksustestid võivad töötada millisekundi kiirusega, kuid testivad komponente isoleeritult. Läbivtestid on aeglasemad, kuid kinnitavad, et kõik süsteemi osad töötavad ühe kooslusena.

Täiuslik testikomplekt sisaldab palju üksusteste, vähem integratsiooniteste ja läbivteste. Seda jaotust nimetatakse sageli testipüramiidiks.