Preskus in analiziranje programske rešitve


Za začetek nekaj programerskih napak

Programska oprema lovskega letala F16 je imela napako, ki je povzročala, da se je letalo obrnilo na glavo, kadarkoli je prečkalo ekvator (napako so odkrili na simulatorju in v resnici ni nikoli prišlo do tega pojava).

Med 1985 in 1987 je računalniško krmiljena naprava Therac-25, uporabljena za obsevanje v bolnišnicah, povzročila zaradi programerske napake pacientom preveliko sevanje. Nekaj pacientov je celo umrlo.

4. junija 1996 je evropska vesoljska raketa Ariane 5 eksplodirala 40 sekund po vzletu. Eksplozijo je povzročila programerska napaka. (Izguba: cca 1 milijarda avstralskih dolarjev).


Pomembnost preskušanja programske opreme

Vsak programer se sreča z nevarnostjo napak. Na nekatere, ki so bolj slovnične napake, ga opozori že prevajalnik. Druge nastopijo v času izvajanja programa. Nekatere so tako zahrbtne, da nastopijo le ob  določenih podatkovnih pogojih. Te je najtežje odkriti, ker včasih niti niso jasno ponovljive. 

Napake in opozorila, ki jih javi že prevajalnik ne bomo posebej obravnavali. Brez odprave napak tako ali tako ne moremo dobiti izvedljivega programa. Smiselno je tudi, da odstranimo vse vzroke za opozorila, ki sama po sebi niso usodna, skrivajo pa nevarnost, da je lahko kaj narobe.

image008

Posvetili se bomo resnejšim napakam, ki se zgode ob času izvajanja programa. Programerji ločijo med programskimi napakami in programskimi izpadi. V primeru izpada program ne naredi tistega, kar od njega pričakujemo. Programska napaka pa je tisto, kar lahko pripelje do programskega izpada (ali pa tudi ne).  Do izpada pride, če pride do nastopa določenih računskih pogojev.

Poznamo več načinov preskušanja programske opreme, vendar  preskušanje kompleksnih programov ni rutinski postopek pač pa že kar proces raziskovanja.

Besedo preskušanje povezujemo tudi s pojmom „dinamična analiza” programa. Pripeljala naj bi do njegove večje zanesljivosti, uinkovitosti, prenosljivosti in možnosti vzdrževanja.

Poznamo štiri nivoje preskušanja programov. Vsak naslednji nivo vključuje tudi predhodji nivo:

Razhroščevalniki

Razhroščevalnik (debugger) je računalniški program, ki ga uporabljamo za preskušanje in razhroščevanje  drugih programov. Razhroščevanje dejansko pomeni odpravljanje napak.

Ko pride do izpada programa, pokaže razhroščevalnik položaj v originalni izvorni kodi, v nekaterih primerih pa kar v strojni kodi (prevedenega) programa, ki ga preskušamo.  

Program izpade (se "sesuje" oziroma "obesi") zaradi neke programske napake. Morda na danem mestu CPE poskuša izvajati dostop do nedostopne lokacije v pomnilniku.

Razhroščevalniki tipično nudijo še boljše možnosti preskušanja. Tako omogočajo koračno sledenje programa od enega do drugega programskega stavka. Najmanj, kar lahko tako vidimo, je, če program res poteka v predvidenem zaporedju stavkov. Ker vmes lahko tudi opazujemo stanja programskih spremenljivk, dobimo tako res podroben vpogled v delovanje programa. Je pa tako pregledovanje programa kljub temu zamudno.


Razhroščevalniki, ki nudijo možnost koračnega sledenja programa, imajo tipično naslednje opcije v "orodni vrstici" ikon, kot jih prikazuje leva slika. Stvar spominja na gumbe na predvajalniku. Poleg normalnega teka programa imamo tudi možnosti za njegovo izvajanje od ukaza do ukaza.



Ker je posebno pri programih, ki vsebujejo kakšne zanke, tako sledenje programa zamudno (kar pomislimo na zanke, ki se morda ponavljajo več stokrat), imajo tipični razhroščevalniki možnost  določanja takoimenovanih "prekinitvenih točk" (breakpoints).

Razhroščevalnik kaže izvorno kodo, mi pa v njej izberemo točko, kjer želimo, da razhroščevalnik izvajanje programa samodejno ustavi. Takih točk je seveda lahko več.  

Če program ne pride do izbrane prekinitvene točke, pomeni, da se je že prej zgodilo nekaj čudnega. Postavimo zato kakšno vmesno prekinitveno točko in poskusimo znova.

Leva slika prikazuje primer takega razhroščevalnika in vzpostavljeno prekinitveno točko za program v jeziku Python.


Preskusni primeri, skripti, zbirke in scenariji preskusov

Za preskusni primer moramo podati primerne vhodne podatke in pričakovane rezultate. Poleg tega lahko podamo tudi sam opis preskusa. Preskusne primere dokumentiramo s primernim oblikovalnikom besedila ali preglednico.

Preskusni skript je kombinacija preskusnega primera, postopka preskušanja in preskusnih podatkov. Preswkusne skripte izvajamo ročno ali avtomatizirano.

Poznamo še zbirke preskusov (test suit), ki vsebujejo za vsak preskus še podrobna navodila in cilje preskusa. Podani so lahko tudi predpogoji, ki morajo biti izpolnjeni za izvedbo nekega preskusa.

Včasih določimo tudi zaporedje preskusov. V tem primeru govorimo o preskusnih scenarijih.


Kako se torej lotiti preskušanja programov?



Najprej moramo spoznati, kaj se s programom dogaja:

  • Se ustavi (se obesi),
  • Daje napačne rezultate,
  • Njegovo izvajanje je nenavadno počasno.

Pripravimo podatke, za katere poznamo, kako se mora program obnašati in kaj mora izpisovati.

Če nimamo druge možnosti, vstavljamo v program vmesne izpise, ki jih potem spremenimo v komentar ali povsem izločimo.

Iskanje napak zelo poenostavi uporaba primernega razhroščevalnika in postavljanje prekinitvenih točk na sumljiva mesta.

Imejmo ogromno potrpljenja!! In bodimo vztrajni!!

Dajmo program preskušati komu drugemu (in zbiramo povratne informacije). Sami smo namreč pogosto ne vidimo lastnih napak. To je tudi smisel že omenjenih alfa in beta testov.