V OSA sisukord |
5.1 TESTIMINE JA SILUMINE
Tarkvara kvaliteet
Nii lühemate kui pikemate programmide puhul on vaja kindel olla, et programm ikka töötab nii nagu nõuded ette näevad ja kasutajad ootavad. Nõuetele ja ootustele vastavuse mõõtu kutsutakse tarkvara kvaliteediks. Tarkvara kvaliteedil võib olla ka teisi tähendusi.
Nõudeid ja ootusi võib olla väga erinevat laadi. Nõuded võivad olla näiteks järgmistes aspektides: hõlpsus (accessibility), ühilduvus (compatibility), konkurrentsus (concurrency), tõhusus (efficiency), funktsionaalsus (functionality), installeeritavus (installability), hooldatavus (maintainability), jõudlus (performance), porditavus (portability), töökindlus (reliability), turvalisus (security), testitavus (testability), kasutatavus (usability). Siintoodud terminid on vastavuses Standardipõhise tarkvaratehnika sõnastikuga.
Erinevates kohtades võidakse erinevaid aspekte erinevalt sõnastada, rõhutada ja rühmitada. Näiteks Tarkvara kvaliteedimudelite standardis ISO/IEC 25010 on esimesel tasemel eristatud kaheksat karakteristikut: funktsionaalne sobivus (functional suitability), soorituse tõhusus (performance efficiency), töökindlus (reliability), ühilduvus (compatibility), kasutatavus (operability), turvalisus (security), hooldatavus (maintainability), porditavus (portability).
Osa eelnevatest terminitest on intuitiivselt paremini mõistetavad, osa vajaks ilmselt põhjalikumat selgitust. Selles kursuses aga keskendume vaid funktsionaalsusele, sest meile on esmajoones tähtis, et programm teeks seda, mida vaja.
Erinevate aspektide kvaliteedi hindamiseks ja ebakohtade leidmiseks kasutatakse erinevaid metoodikaid. Vahel on vaatluse all kogu süsteem tervikuna. Teatud juhtudel on aga mõistlik vaadata erinevaid osi eraldi. Tarkvara arendamisel on sageli suur osa kvaliteedi kontrollist otsesest programmeerimisest lahku viidud - sellega tegelevad spetsiaalsed inimesed (osakonnad). Samuti on tarkvara otsene programmeerimine ise tavaliselt jaotatud erinevate inimeste vahel.
Kui üks inimene ühe programmilõigu kirjutab, on ta harilikult ise ka esmane kontrollija. Seda olete meie kursuselgi korduvalt ülesandeid lahendades teinud.
Edasi vaatame, kuidas süstemaatiliselt kontrollida programmi funktsionaalsust - kuivõrd programm teeb seda, mis nõutud.
Testimine
Tarkvara kontrollimisel on tähtis osa testimisel (kontrollimisel kasutatakse nt ka läbivaatust, tõestamist ja muid meetodeid). Testimisel on erinevaid definitsioone. Siin võtame testimist kitsalt kui programmi käivitamist nõuetele vastavuse kontrollimiseks ja vigade leidmiseks.
Üldjuhul avastatakse testimise käigus suurem osa programmis leiduvatest vigadest. Mida põhjalikum on testimine, seda kvaliteetsem on lõpptulemus. Testimine algab tegelikult juba programmi kirjutamisel. Iga kord kui programmi käivitame ja proovime, kas näiteks äsjakirjutatud funktsioon annab loodetud tulemuse või kas programm üldse käivitub, tegelemegi juba testimisega.
Testimine on oluline tarkvara arenduse erinevatel etappidel, seejuures testitakse tarkvara nii tervikuna kui ka osade kaupa. Ühe konkreetse üksuse (nt funktsiooni) testimist nimetatakse ühiktestimiseks (unit testing). Ühiktestimiseks võivad programmeerimiskeeltes olla spetsiaalsed vahendid. Näiteks Pythonis võib selleks kasutada lihtsat assert
lauset:
def paaris_liitmine(x): if x % 2 == 0: return x + 1 return x assert paaris_liitmine(1) == 1 assert paaris_liitmine(0) == 1
Näitena vaatleme funktsiooni paaris_liitmine(x)
testimist. Olgu nõuetes kirjas, et funktsioon peab paarisarvulise argumendi korral tagastama sellest argumendist ühe võrra suurema arvu, vastasel juhul argumendi enda.
Märksõnale assert
järgneb tingimus, mis peab tõene olema. Kui tingimus on tõene, siis programm ei tee mitte midagi; kui tingimus on väär, siis antakse veateade (AssertionError
).
Nii saab funktsiooni tööd kontrollida mitmete erinevate argumentidega. Kui testitav funktsioon peaks mingil hetkel muutuma, kuid selle jaoks on testid (assert
-laused) alles, siis saab nende abil automaatselt funktsiooni uuesti testida.
Pythonis on olemas ka moodul unittest, mis võimaldab paindlikumat testimist, kuid nõuab algteadmisi objekt-orienteeritud programmeerimisest:
import unittest def paaris_liitmine(x): if x % 2 == 0: return x + 1 return x class UusTest(unittest.TestCase): # Uus klass def test(self): self.assertEqual(paaris_liitmine(1), 1) # 1. testjuht self.assertEqual(paaris_liitmine(0), 1) # 2. testjuht if __name__ == '__main__': unittest.main()
Klassis UusTest
on funktsioon test
, milles on omakorda kaks testjuhtu (test case).
Programmi käivitades ilmub ekraanile muuhulgas
Ran 1 test in 0.000s OK
Proovige funktsiooni paaris_liitmine
muuta nii, et kontrollis "läbi kukutakse". Näiteks
def paaris_liitmine(x): if x % 2 == 0: return x + 2 return x
Proovige ka funktsiooni, mis olenemata argumendist tagastab arvu 1
. Kas test läbitakse?
def paar_liitmine(x): return 1
Lähemalt testimisest saab lugeda näiteks Python dokumentatsioonist.
Testjuhud
Testjuhud koosnevad sisendandmetest ja nendele vastavatest oodatavatest väljundandmetest. Eelnevas näites olid testjuhud, kus
- sisend oli 0 ja sellele vastav väljund 1 ning
- sisend oli 1 ja sellele vastav väljund 1.
Testimist peaks korraldama süstemaatiliselt. Selles on väga oluline mõistlike testjuhtude komplekti moodustamine. Täielikult süstemaatilise lähenemise kõrval on siiski omal kohal ka vähem süstemaatilised võtted. Näiteks suitsutesti (smoke testing) korral kontrollitakse vaid, kas programmi põhiasjad töötavad. Nimetus on pärit ammuste aegade elektroonika seadmetest, kui vigade korral päriselt suitsu võiski tulema hakata.
Kuna programmeerija ise on oma programmiga liiga seotud, siis tema enda koostatud testjuhud ei pruugi olla piisavalt head. Võimalik, et ka Teil on juhtunud, et enda arvates ju programm töötab hästi, aga automaatkontroll toob veel välja juhte, mille puhul programm õigesti ei tööta.
Nii programmeerijal endal kui ka teistel testijatel (testjuhtude koostajatel) on kasulik teada, mis alusel testimist läbi viia. Eristada saab näiteks valge kasti, läbipaistva kasti (white box) meetodeid ja musta kasti (black box) meetodeid. Nagu tänapäeval paljude asjadega, on siingi võimalikud halli kasti (grey box) meetodid.
Musta kasti meetodi puhul ei vaadelda üldse programmi teksti ja testjuhud on valitud ainult nõuete põhjal. Programmi käsitletakse kui "musta kasti", teadmata midagi selle sisemisest tööst. Testija sisestab mingid andmed ja saab vastuseks tulemuse, teadmata, mida andmetega vahepeal tehakse ning kontrollib, kas tulemus ja programmi käitumine on ootuspärane. Valge kasti meetodi korral vaadeldakse ka programmi ja testjuhtude koostamisel arvestatakse muuhulgas konkreetse testitava programmiga.
Programmi võimalike sisendandmete hulk on tavaliselt väga suur ja programmi testimine kõigil võimalikel juhtudel võimatu. Niisiis tuleb teha mõistlik valik.
Silumine
Vigade leidmisel peaks need ka kõrvaldama. Vigade kõrvaldamise protsessi nimetatakse silumiseks (debugging). Legendi järgi tuleneb ingliskeelne nimetus 1940ndate aastate keskpaigast, kui tollaste suurte arvutite tööd mõni putukas (bug) võis tõsiselt häirida.
Tänapäevaste programmeerimisvahendite koosseisus on sageli ka silur (debugger). Silur võimaldab näiteks seisatada programmi selle töötamise käigus, et uurida, millised muutujad on väärtustatud ja mis väärtus neil parajasti on. Siluriga on programmikoodi võimalik ridahaaval läbida. Ka Thonnys on siluri kasutamise võimalus olemas ("putukaga" nupp või Run --> Debug current script).
Lisaks on tänapäevastes programmeerimisvahendites ka mõeldud sellele, et vigu üldse vähem teha. Näiteks püütakse aidata nimede kirjutamisel, sulgude tasakaalustamisel, treppimisel vms.
Lõpetuseks
Üsna populaarseks on näiteks muutunud testipõhine arendus (test driven development), mille korral esmajärjekorras töötatakse välja testid. Täpsemalt saab lugeda näiteks siit (inglise keeles).
Eesti keeles on tarkvara protsessidest, kvaliteedist ja standarditest põhjalikult kirjutanud Jaak Tepandi Tallinna Tehnikaülikooli Informaatikainstituudist. Seal on juttu ka testimisest. Inglise keeles on testimisest palju kirjutatud, näiteks siin.
V OSA sisukord |