testiranje programske opreme · 2017. 11. 28. · iv testiranje programske opreme ključne besede:...
TRANSCRIPT
-
UNIVERZA V MARIBORU
FAKULTETA ZA ELEKTROTEHNIKO, RAČUNALNIŠTVO IN
INFORMATIKO
Tadej Moharič
TESTIRANJE PROGRAMSKE OPREME
Diplomsko delo
Maribor, oktober 2015
-
i
Diplomsko delo visokošolskega strokovnega študijskega programa
TESTIRANJE PROGRAMSKE OPREME
Študent: Tadej Moharič
Študijski program: Visokošolski strokovni, Računalništvo in informatika
Smer: Programska oprema
Mentor: red. prof. dr. Peter Kokol
Lektorica: Tanja Kamenšek, prof.
Maribor, oktober 2015
-
ii
-
iii
ZAHVALA
Zahvaljujem se mentorju, prof. dr. Petru Kokolu, za
nasvete in pomoč pri izdelavi diplomskega dela.
Posebna zahvala tudi staršem, ki so mi omogočili
študij.
-
iv
Testiranje programske opreme
Ključne besede: testiranje programske opreme, razvoj programske opreme, testiranje,
poraba pomnilnika, ogrodje QT
UDK: 004.258:004.4'24(043.2)
Povzetek
V diplomskem delu predstavimo proces testiranja programske opreme. Na začetku
podamo pregled zgodovine testiranja programske opreme ter osnov testiranja le-te, nato
raziščemo različne stopnje in tipe testiranja ter kako najbolje dokumentiramo rezultate, da
lahko razvijalci hitro najdejo in odpravijo najdene napake. Ko s tem končamo, predstavimo
razvoj QT C++ aplikacije, ki jo lahko poganjamo na različnih operacijskih sistemih
(Windows, Linux) in spremljamo porabo pomnilnika aplikacije, ki jo testiramo. Na koncu
dela našo aplikacijo uporabimo za testiranje porabe pomnilnika same aplikacije na
različnih operacijskih sistemih in predstavimo rezultate.
-
v
Software testing
Key words: software testing, software development, testing, memory usage, QT
framework
UDK: 004.258:004.4'24(043.2)
Abstract
In the thesis the process of software testing is introduced. In the first part history of
software testing and the basics of it are presented. After that the different stages and
types of software testing and the best way to document testing results so that developers
can find and eliminate bugs efficiently are examined. In the following chapters the
development of a QT C++ application, which can be used to track the memory usage of
the application in the process of testing is explained. The testing application works on
different operating systems (Windows, Linux). In the last chapter the memory
consumption of our application itself is tested and results are presented.
-
vi
KAZALO
1 UVOD ........................................................................................................................ 1
2 ZGODOVINA TESTIRANJA PROGRAMSKE OPREME ........................................... 2
3 OSNOVE TESTIRANJA ............................................................................................ 3
3.1 Osnovni proces testiranja ....................................................................................... 4 3.1.1 Planiranje in nadzor ........................................................................................ 6 3.1.2 Analiza in načrtovanje ..................................................................................... 6 3.1.3 Izvedba in poganjanje ..................................................................................... 7 3.1.4 Vrednotenje izhodnih kriterijev in poročanje .................................................... 7 3.1.5 Zaključevanje testnih aktivnosti ....................................................................... 8
4 STOPNJE TESTIRANJA PROGRAMSKE OPREME ................................................ 9
4.1 Testiranje modulov ............................................................................................... 10
4.2 Integracijsko testiranje .......................................................................................... 13
4.3 Sistemsko testiranje ............................................................................................. 14
4.4 Testiranje sprejemljivosti ...................................................................................... 15 4.4.1 Uporabniško testiranje sprejemljivosti ........................................................... 16 4.4.2 Operativno testiranje ..................................................................................... 16 4.4.3 Testiranje pogodbenih sprejemljivosti ............................................................ 16
4.5 Alpha testiranje .................................................................................................... 17
4.6 Beta testiranje ...................................................................................................... 17
4.7 Testiranje novih verzij in popravkov ...................................................................... 17
5 TIPI TESTIRANJA ................................................................................................... 19
5.1 Funkcionalno testiranje ........................................................................................ 19
5.2 Nefunkcionalno testiranje ..................................................................................... 19
5.3 Regresijsko testiranje ........................................................................................... 21
5.4 Statično testiranje ................................................................................................. 22 5.4.1 Pregled ......................................................................................................... 22 5.4.2 Statična analiza ............................................................................................. 24
5.5 Dinamično testiranje ............................................................................................. 25 5.5.1 Pristop črne škatle ......................................................................................... 26 5.5.2 Pristop bele škatle ......................................................................................... 26 5.5.3 Intuitivno testiranje ........................................................................................ 26
6 AVTOMATIZACIJA TESTIRANJA .......................................................................... 28
7 DOKUMENTIRANJE TESTIRANJA IN JAVLJANJE HROŠČEV............................ 30
8 PREDSTAVITEV UPORABLJENIH ORODIJ .......................................................... 32
8.1 Ogrodje QT .......................................................................................................... 32
8.2 Oracle VirtualBox ................................................................................................. 34
9 RAZVOJ APLIKACIJE ZA TESTIRANJE PORABE POMNILNIKA ........................ 36
9.1 Izbira procesa in nastavitev .................................................................................. 38
9.2 Pridobivanje podatkov o pomnilniku ..................................................................... 42
-
vii
9.3 Spremljanje porabe pomnilnika ............................................................................ 42
9.4 Shranjevanje pridobljenih podatkov v CSV-datoteko ............................................ 48
9.5 Shranjevanje pridobljenih podatkov v SQLite podatkovno bazo ........................... 48
9.6 Branje in prikaz podatkov shranjenih v podatkovni bazi ........................................ 51
9.7 Shranjevanje in branje nastavitev ......................................................................... 54
10 TEST S POMOČJO RAZVITE APLIKACIJE ........................................................... 55
10.1 Test aplikacije na operacijskem sistemu Windows ............................................... 55
10.2 Test aplikacije na operacijskem sistemu Linux ..................................................... 57
11 SKLEP .................................................................................................................... 59
12 VIRI IN LITERATURA ............................................................................................. 61
13 PRILOGE ................................................................................................................ 62
13.1 Naslov študenta ................................................................................................... 62
13.2 Kratek življenjepis ................................................................................................ 62
KAZALO SLIK
SLIKA 3.1: WATERFALL MODEL ............................................................................................ 5
SLIKA 3.2: OSNOVNI PROCES TESTIRANJA ............................................................................ 5
SLIKA 4.1: V-MODEL ........................................................................................................... 9
SLIKA 4.2: VERIFIKACIJA IN VALIDACIJA .............................................................................. 10
SLIKA 5.1: TESTNO OKOLJE ............................................................................................... 25
SLIKA 8.1: QT-SIGNALI IN REŽE.......................................................................................... 32
SLIKA 8.2: QT-CREATOR................................................................................................... 33
SLIKA 8.3: VIRTUALBOX ̶ NAVIDEZNE NAPRAVE .................................................................. 34
SLIKA 8.4: DEBIAN LINUX V VIRTUALBOX NAVIDEZNI NAPRAVI .............................................. 35
SLIKA 9.1: GLAVNO OKNO ................................................................................................. 36
SLIKA 9.2: TIPI POMNILNIKA – WINDOWS ............................................................................ 40
SLIKA 9.3: TIPI POMNILNIKA – LINUX .................................................................................. 40
SLIKA 9.4: IZBIRA BARVE ................................................................................................... 41
SLIKA 9.5: SPREMLJANJE PORABE POMNILNIKA ................................................................... 43
SLIKA 9.6: PRIKAZ TREND PREMICE .................................................................................... 47
SLIKA 9.7: CSV-DATOTEKA ............................................................................................... 48
SLIKA 9.8: PODATKOVNA BAZA .......................................................................................... 49
SLIKA 9.9: OKNO S PRIKAZOM PRETEKLIH SEJ ..................................................................... 51
SLIKA 9.10: PRIKAZ GOLIH PODATKOV ................................................................................ 53
SLIKA 10.1: TEST APLIKACIJE NA WINDOWS 10 ̶ GLAVNO OKNO .......................................... 56
-
viii
SLIKA 10.2: TEST APLIKACIJE NA WINDOWS 10 ̶ REZULTATI ................................................ 56
SLIKA 10.3: TEST APLIKACIJE NA DEBIAN 8 – GLAVNO OKNO ................................................ 57
SLIKA 10.4: TEST APLIKACIJE NA DEBIAN 8 – GRAF ............................................................. 58
SLIKA 10.5: TEST APLIKACIJE NA DEBIAN 8 – PODATKI ........................................................ 58
KAZALO IZVORNE KODE
IZVORNA KODA 4.1: FUNKCIJA ODŠTEJ POPUST .................................................................. 11
IZVORNA KODA 4.2: FUNKCIJA ZA TESTIRANJE FUNKCIJE ODSTEJPOPUST ............................. 11
IZVORNA KODA 9.1: POVIŠANJE PRIVILEGIJEV APLIKACIJE .................................................... 37
IZVORNA KODA 9.2: PRIDOBIVANJE TRENUTNO AKTIVNIH PROCESOV .................................... 38
IZVORNA KODA 9.3: PRIDOBIVANJE IMENA IZBRANEGA PROCESA .......................................... 39
IZVORNA KODA 9.4: DODAJANJE PRIDOBLJENIH PODATKOV V DREVO .................................... 39
IZVORNA KODA 9.5: DODAJANJE TIPA POMNILNIKA V DREVO ................................................. 40
IZVORNA KODA 9.6: PRIDOBIVANJE PODATKOV O PORABI POMNILNIKA .................................. 42
IZVORNA KODA 9.7: DEFINICIJA SIGNALA IN REŽE ZA POSODOBITEV GRAFA ........................... 44
IZVORNA KODA 9.8: POVEZAVA SIGNALA IN REŽE TER ZAGON NITI, KI PRIDOBIVA PODATKE ..... 44
IZVORNA KODA 9.9: PREVERJANJE PORABE POMNILNIKA V SVOJI NITI ................................... 44
IZVORNA KODA 9.10: INICIALIZACIJA VEKTORJA ZA OS X NA GRAFU ...................................... 45
IZVORNA KODA 9.11: POSODABLJANJE GRAFA .................................................................... 46
IZVORNA KODA 9.12: PSEVDOKOD IZRAČUNA TREND PREMICE ............................................. 47
IZVORNA KODA 9.13: PRIPRAVA SQL-UKAZA TER PROŽENJE SIGNALA .................................. 49
IZVORNA KODA 9.14: REŽA ZA DODAJANJE UKAZA V ČAKALNO VRSTO ................................... 50
IZVORNA KODA 9.15: PSEVDOKOD PREVERJANJA ČAKALNIH VRST ........................................ 50
IZVORNA KODA 9.16: DODAJANJE UKAZA ZA BRANJE V VRSTO .............................................. 52
IZVORNA KODA 9.17: PSEVDOKOD DODAJANJA PREJETIH REZULTATOV V SEZNAM ................. 52
IZVORNA KODA 9.18: IZBRIS SEJE IN PODATKOV .................................................................. 53
-
ix
UPORABLJENE KRATICE
PID – identifikator procesa (angl. process identifier)
OS – operacijski sistem (angl. operating system)
CSV – vrednosti ločene z vejico (angl. comma-separated values)
UTP – neoklopljen prepleteni par (angl. unshielded twisted pair)
MOC – prevajalnik meta elementov (angl. meta-object compiler)
IDE – integrirano razvojno okolje (angl. integrated development enviroment)
SQL – strukturirani jezik za poizvedovanje (angl. structured query language)
RAM – pomnilnik z naključnim dostopom (angl. random access memory)
VRAM – grafični pomnilnik z naključnim dostopom (angl. video RAM)
HDD – trdi disk (angl. hard data disk)
-
Testiranje programske opreme
1
1 UVOD
Dandanes, ko je uporaba računalnikov skorajda samoumevna in si življenja brez njih ne
moremo več predstavljati, je na voljo na milijone različnih aplikacij, ki nam pomagajo pri
delu, razvedrilu, hišnih opravilih, stiku z našimi bližnjimi in še ogromno različnih funkcijah.
Obstajajo aplikacije, na katere sploh ne pomislimo, ko delujejo pravilno; na primer
aplikacije, ki skrbijo za delovanje jedrskih elektrarn, finančnih inštitucij, borze, krmiljenje
kirurških robotov. Če pa bi v takšnih aplikacijah prišlo do kakšne koli napake, bi bile lahko
posledice katastrofalne. Uporabniku, ki potrebuje aplikacijo za izpolnitev nekega cilja in
ima na voljo več konkurenčnih aplikacij, je seveda pomembno, da je ta enostavna za
uporabo in da vsebuje vse funkcije, ki jih on potrebuje. Zelo pomembno je tudi, da deluje
stabilno in pravilno – na primer, če se uslužbenec na banki zmoti pri pologu in v vrstico za
znesek pomotoma vpiše še kakšen drug znak, ga mora aplikacija, ki je bila pravilno
napisana in testirana, na to opozoriti, medtem ko lahko aplikacija, ki ni bila dovolj
testirana, ta vnos dovoli in komitentu doda nepravilen znesek na njegov račun ali pa celo
pokvari bazo podatkov, tako da je program ne more več prebrati.
Podjetja bodo raje kupila konkurenčni program ne glede na to, da je dražji ali mogoče
izgleda slabše na prvi pogled, če bo v preizkusnem obdobju pri programu našla hrošče, ki
upočasnjujejo ali onemogočajo učinkovito delo z aplikacijo. Zaradi tega je testiranje
programske opreme zelo pomemben del razvoja programske opreme.
V tem diplomskem delu bomo raziskali testiranje programske opreme. Najprej bomo
predstavili orodja, s pomočjo katerih bomo razvili aplikacijo za spremljanje porabe
pomnilnika na različnih operacijskih sistemih, ter orodja, s katerimi bomo našo
programsko opremo uporabili pri testiranju. Nato bomo predstavil kratko zgodovino ter
osnove testiranja in raziskali in predstavili različne stopnje in tipe testiranja. Ko bomo s
tem zaključili pa se bomo lotili razvoja QT C++ aplikacije za spremljanje porabe
pomnilnika ter aplikacijo uporabili tako, da bomo zasnovali test, ki bo preveril porabo
njenega pomnilnika. Na koncu bomo predstavili rezultat testa.
-
Testiranje programske opreme
2
2 ZGODOVINA TESTIRANJA PROGRAMSKE OPREME
Naslednja klasifikacija izvira iz leta 1988 in sta jo ustvarila D. Gelperin in W. C. Hetzel.
Testiranje sta razdelila v naslednja obdobja:
Do leta 1956 je bilo razhroščevalno obdobje, saj ni obstajala nobena razlika med
testiranjem in razhroščevanjem.
Od 1957 do 1978 leta je bilo demonstracijsko naravnano obdobje, tedaj se je že
opazila razlika med razhroščevanjem in testiranjem. V tem obdobju se je največ
testiralo, ali programska oprema zadošča postavljenim zahtevam.
Glavni cilj testiranja med 1979 in 1982 v destruktivno naravnanem obdobju je bil,
da se najdejo napake.
Obdobje med 1983 in 1987 sta poimenovala preizkusno obdobje. V tem obdobju
se je preizkuševalo programsko opremo med njeno življenjsko dobo ter preverjalo
njeno kakovost.
Od 1988 dalje pa je obdobje preventivnega testiranja, ko so izvedeni testi
namenjeni temu, da preverimo, ali programska oprema sledi postavljenim
specifikacijam [2].
Novejše klasifikacije zgodovine programske opreme nismo zasledili, smo pa našli nekaj
pomembnih mejnikov:
Na koncu osemdesetih se je pojavilo tako imenovano »fuzz« testiranje – to je testiranje z
naključnimi, nestrukturiranimi podatki.
V začetku devetdesetih je bil izdan standard ISO 9126. V njem je kvaliteta programske
opreme razdeljena na šest delov (funkcionalnost, zanesljivost, uporabnost, učinkovitost,
vzdržljivost in prenosljivost). Leta 1998 je britanska organizacija »Information Systems
Examinations Boards« začela s certificiranjem preizkuševalcev programske opreme.
Istega leta je izšla tudi prva različica popularnega orodja za spremljanje hroščev Bugzilla.
Leto kasneje (1999) je International Institute for Software Testing začel ponujati Certified
Software Test Professional certifikacije.
Kasneje, novembra 2002, je bila ustanovljena organizacija ISTQB (International Software
Testing Qualifications Board), ki certificira testerje po vsem svetu.
Leta 2011 je bil izdan standard ISO 25010, ki je nadomestil standard ISO 9126. Standard
definira zahteve in vrednotenje za kakovost računalniških sistemov in programske opreme
[12].
-
Testiranje programske opreme
3
3 OSNOVE TESTIRANJA
Testiranje programske opreme je proces, s katerim preverjamo aplikacijo oziroma
program z namenom, da najdemo napake in odstopanja. S testiranjem preverimo tudi, ali
programska oprema izpolnjuje zahteve in deluje po specifikacijah, ki so bile postavljene.
Testiranje programske opreme je potrebno, ker delamo napake vsi in medtem ko so
nekatere napake nepomembne, so druge lahko zelo drage in celo nevarne, zato je
priporočljivo, da preverjamo vse kar ustvarimo – ne samo programske opreme.
Programska oprema, ki jo ustvarimo, lahko ima napake zaradi napačnih predpostavk in
stvari, na katere smo pozabili, zato je velika možnost, da pri testiranju lastne aplikacije te
napake spregledamo. Najbolje je, da programsko opremo testira nekdo, ki pri načrtovanju
in implementaciji ni sodeloval, saj je tako večja možnost, da opazi napake, ki bi jih
drugače sami spregledali [11].
Preden se lotimo testiranja, moramo vedeti, kdaj programska oprema deluje pravilno – v
skladu z zahtevami, saj lahko edino tako zagotovo vemo, da je nekaj narobe, ko naletimo
na napako. Program deluje narobe, ko obstaja razlika med rezultatom, ki ga aplikacija
vrne, in kako se aplikacija obnaša s tem, kar se pričakuje da bo program vrnil oziroma
kako se bo obnašal. To pomeni, da je napaka prisotna, ko uporabniško pričakovanje ni
izpolnjeno. Na primer tudi če aplikacija vrne pravilen rezultat, ampak je pretežka ali
prepočasna za uporabo oziroma upočasnjuje celoten delovni proces.
Programska oprema brez hroščev ne obstaja (razen mogoče kakšnih trivialnih primerov,
kot so Hello World aplikacija ipd.). Po navadi pri načrtovanju in implementaciji
spregledamo robne primere, kot je npr. nepravilno število dni v prestopnem letu, vnos
negativnega števila pri teži ipd., zato moramo razumeti, da s testiranjem ne moremo
dokazati, da hroščev ni. S testiranjem lahko najdemo večino hroščev, ne pa vseh, saj ne
moremo nikoli predvideti in preveriti vseh možnih scenarijev in testnih primerov.
Najpogostejši vzrok napak v programski opremi so človeške napake, ki so številčnejše, če
so razvijalci pod stresom zaradi časovnih omejitev, če izvorno kodo spreminja tretja
oseba, ki je v osnovi ni napisala ter ne pozna vseh posledic, ki jih prinesejo njene
spremembe itd… Velikokrat pa so hrošči skriti v izvorni kodi, ki se nikoli ne izvede zaradi
kakšnega drugega hrošča, in začnejo povzročati težave komaj takrat, ko jih odpravimo. To
nam oteži testiranje, saj moramo poleg testov, s katerimi smo neko napako odkrili,
popravljeno aplikacijo testirati tudi za stvari, na katere bi lahko ta popravek vplival [11].
-
Testiranje programske opreme
4
Da lahko razvijalec napako odpravi, jo mora najprej najti v izvorni kodi. Pri tem si pomaga
z dokumentacijo, ki jo je dobil od preizkuševalca ter z razhroščevanjem (ki ga veliko ljudi
napačno enači s testiranjem). Testiranje programske opreme je namenjeno:
iskanju napak,
ocenitvi kvalitete programa,
poganjanju programa za pridobitev zaupanja – če temeljiti test najde malo ali
nobeno napako, bomo imeli večje zaupanje vanj in ga bomo z večjo vnemo in
gotovostjo reklamirali in priporočali potencialnim strankam [11].
Proces testiranja je sestavljen iz:
planiranja testov,
načrtovanja testov,
izvrševanja testov,
analiziranja rezultatov testiranja [11].
Priporočljivo je, da več testov združimo, tako da rezultat prvega testa uporabimo za
vhodne podatke v drugem testu, rezultat drugega testa pa pri tretjem testu itn… Če
imamo neko podatkovno bazo, bomo v prvem testu vanjo zapisali neke podatke, v
drugem testu te podatke spremenimo, v tretjem jih preberemo, v četrtem pa jih izbrišemo
iz podatkovne baze. Takšnemu združevanju testov rečemo testni scenariji.
Testi so lahko poimenovani po:
namenu testa (npr. obremenitveni test),
tehniki testiranja,
testiranemu objektu (npr. test grafičnega vmesnika, test podatkovne baze),
osebi, ki izvaja testiranje (npr. test razvijalca, uporabniški test) [11].
3.1 Osnovni proces testiranja
Proces razvoja programske opreme običajno poteka po izbranem modelu razvoja
programske opreme, s katerim je delo organizirano in brez prekinitev. V vsakem modelu
je tudi prostor za testiranje programske opreme, vendar ne v enakem obsegu.
Najstarejši model je t. i. »Waterfall model« (Slika 3.1), ki je zelo enostaven. Vsaka nova
faza razvoja se lahko začne samo, ko zaključimo s trenutno. Testiranje v tem modelu je
zanemarjeno, saj je zanj namenjena samo ena faza v razvoju – zadnja faza pred izdajo
-
Testiranje programske opreme
5
programske opreme in jo v tem primeru lahko enačimo s pregledom nekega fizičnega
izdelka preden ga predamo kupcu.
Sistemske zahteve
Programske zahteve
Analiza
Načrtovanje
Kodiranje
Testiranje
Uporaba
Slika 3.1: Waterfall model
Izboljšava tega modela je V model (Slika 4.1), v katerem je testiranje ločeno od drugih
aktivnosti in poteka na različnih stopnjah med celotnim procesom in ne samo na koncu.
Ker je samo testiranje v teh modelih opisano na splošno, ga je potrebno razčleniti na več
delov [11] (Slika 3.2).
Planiranje innadzor
Analiza in načrtovanje
Izvedba in poganjanje
Vrednotenje izhodnih kriterijev in poročanje
Zaključevanje testnih aktivnosti
Slika 3.2: Osnovni proces testiranja
-
Testiranje programske opreme
6
3.1.1 Planiranje in nadzor
V prvi stopnji planiramo celoten proces testiranja. To vključuje:
določevanje ciljev testiranja in ocenitev tveganja,
določevanje pristopa k testiranju,
ustvarjanje strategije testiranja - strategija testiranja je osnutek, ki opiše testiranje
v našem razvojnem ciklu. Ustvarimo ga, da vodjo projekta, razvijalce,
preizkuševalce seznanimo s cilji in metodami testiranja ter časom in sredstvi, ki so
za testiranje na voljo,
ugotavljanje sredstev, ki jih bomo za testiranje potrebovali (ljudi, računalnikov,
programske opreme itn.),
določitvi urnika ozioroma plana testiranja, pri katerem določimo, koliko časa
imamo za vsako posamezno stopnjo testiranja,
določanje izhodnih kriterijev, kot je kriterij pokritja (angl. »coverage criteria«), ki
nam pove, koliko odstotkov vrstic v kodi mora biti pognanih med testiranjem. To
nam pomaga pri ugotavljanju, kako daleč smo s testiranjem in kdaj smo s
testiranjem zaključili [11].
Nadzor je namenjen spremljanju testnih aktivnosti. Med nadziranjem primerjamo
opravljeno delo z načrtom in poskrbimo, da so načrtovani cilji izpolnjeni. Če je potrebno
moramo načrt testiranja tudi posodobiti.
3.1.2 Analiza in načrtovanje
Najprej moramo pregledati specifikacije programa (Dokumenti, ki so bili ustvarjeni med
razvojem programske opreme ter zahteve, ki nam jih je postavil naročnik.), ki ga bomo
testirali. Temu rečemo testna baza. Specifikacije morajo biti točne in razumljive, saj v
nasprotnem primeru ne moremo načrtovati in izvajati testov. Če ni točno določeno, kaj
mora v nekem primeru aplikacija vrniti, ne moremo narediti in izvesti testa za ta primer
oziroma ne vemo, ali je rezultat, ki nam ga je aplikacija vrnila, pravilen, saj ne moremo
primerjati rezultata testa z rezultatom definiranim v specifikacijah, ki naj bi bil pravilen. Ko
pregledamo specifikacije, raziščemo preizkusljivost (angl. »testability«) zahtev. Če lahko
test razbijemo na več manjših, so ti testi enostavnejši in je testiranje lahko lažje. Kako
podrobno testiramo določene dele programske opreme, smo določili v prejšnji fazi pri
-
Testiranje programske opreme
7
ustvarjanju strategije testiranja. Če je velika verjetnost, da bo prišlo do napak v nekem
delu aplikacije, za ta del načrtujemo bolj podrobne teste, če pa je verjetnost za to majhna,
se odločimo za preprostejše. To upoštevamo pri načrtovanju, ki se ga lotimo tako, da
definiramo t. i. logične teste, ki nimajo definiranih specifičnih vhodnih pogojev. Na primer
če imamo aplikacijo kalkulator, bo eden izmed logičnih testov »preveri rezultat vsote dveh
števil«, eden izmed konkretnih testov oziroma testnih primerov (angl. »test case«) tega
logičnega testa pa bo »preveri rezultat vsote števil 10 in 5«. Na koncu moramo zasnovati
in izbrati testno okolje, v katerem ga bomo poganjali. Pri tem si pomagamo s tem, da
najprej preverimo, katero programsko in strojno opremo bomo za izvedbo potrebovali [11].
3.1.3 Izvedba in poganjanje
V tej fazi vzpostavimo testno okolje z vsemi orodji, ki jih bomo potrebovali za izvedbo
testov ter ustvarimo testne primere za vsak logični test. To storimo tako, da izberemo
konkretne podatke in jih vstavimo v logične teste. Testne primere nato izvedemo. Pri
izvajanju vodimo testni dnevnik, v katerega beležimo rezultate, ki jih aplikacija vrača, na
koncu pa primerjamo dobljene rezultate s pričakovanimi, da vidimo, ali je programska
oprema teste prestala ali ne. V tej fazi ponovno izvajamo teste na popravljeni aplikaciji, da
preverimo, ali so bile napake odpravljene [11].
3.1.4 Vrednotenje izhodnih kriterijev in poročanje
Tukaj preverimo, če smo dosegli postavljene izhodne kriterije. To se zgodi:
ko pade število najdenih hroščev pod določeno stopnjo,
ko je največ testnih primerov teste prestalo,
ko smo dosegli postavljene roke za testiranje.
Oceniti moramo, ali je potrebno testiranje nadaljevati, in če je potrebno spremeniti izhodne
kriterije, ki jih ovrednotimo tako, da primerjamo testne dnevnike z izhodnimi kriteriji, ki smo
jih definirali med planiranjem. Na koncu napišemo še poročilo o testiranju [11].
-
Testiranje programske opreme
8
3.1.5 Zaključevanje testnih aktivnosti
Ta stopnja se velikokrat izpusti zaradi pomanjkanja časa. V njej analiziramo izkušnje, ki
smo jih s testiranjem pridobili, še posebej nas zanimajo odstopanja med planiranjem in
dejansko izvedbo testiranja. Priporočljivo je tudi shraniti naslednje podatke:
Kdaj je bilo testiranje končano ali prekinjeno?
Kdaj smo dosegli pomembne mejnike?
Kdaj je bila programska oprema oziroma posodobitev izdana?
Na koncu moramo shraniti še skripte in druga programska orodja, ki smo jih pri testiranju
uporabili, saj jih bomo zagotovo potrebovali pri testiranju novih verzij in popravkov
programske opreme [11].
-
Testiranje programske opreme
9
4 STOPNJE TESTIRANJA PROGRAMSKE OPREME
Testiranje programske opreme bomo raziskali v najbolj uporabljenem modelu – modelu V
(Slika 4.1). V njem je testiranje programske opreme enakovredno razvoju in programiranju
le-te in je zato dosti boljši od t. i. waterfall modela.
Kodiranje
Specifikacija modulov
Tehnična zasnova
Funkcionalna zasnova
Opredelitev zahtev
Testiranje modulov
Integracijsko testiranje
Sistemsko testiranje
Testiranje sprejemljivosti
Slika 4.1: V-model
V tem modelu je za vsako stopnjo razvoja definirana stopnja testiranja:
Pri testiranju modulov oziroma komponent preverimo, ali vsak
modul/komponenta ustreza specifikacijam.
Pri integracijskem testiranju preverimo, ali moduli, povezani v neko celoto,
delujejo, kot je bilo definirano pri tehnični zasnovi.
Sistemsko testiranje je namenjeno temu, da preverimo, ali produkt kot celota
ustreza specificiranim zahtevam.
Pri testiranju sprejemljivosti preverimo, ali aplikacija izpolnjuje zahteve, ki so bile
dogovorjene s stranko v pogodbi [11].
Na začetku testiranja opravimo verifikacijo, kjer preverimo, ali programska oprema
vsebuje vse funkcionalnosti, ki jih stranka potrebuje. To preverimo tako, da se poglobimo
-
Testiranje programske opreme
10
v dokumente, načrte, zahteve, specifikacije in kodo. Če na primer delamo pisarniški stol,
verifikacijo začnemo s tem, da preverimo vse dele stola ̶ ali so vse noge enake velikosti,
je naslonjalo enako visoko na obeh straneh, ali zdrži osebo do največje določene teže
itd… Z verifikacijo potrdimo, da poteka izdelava aplikacije pravilno, ter demonstriramo
pravilnost programske opreme na vsaki stopnji razvoja.
Proti koncu razvoja pa moramo preveriti, ali programska oprema opravlja funkcije, za
katere je namenjena. Temu procesu pravimo validacija. Medtem ko se pri verifikaciji
sprašujemo, ali produkt deluje pravilno, se pri validaciji sprašujemo, ali delamo pravilen
produkt ̶ aplikacija lahko uspešno prestane verifikacijo, pade pa v procesu validacije. To
se lahko zgodi, ko se produkt oziroma deli produkta skladajo s specifikacijo, ko pa imamo
delujočo aplikacijo, pa validacije ne prestane zaradi nepopolnih ali napačnih specifikacij
[11].
Potrebe in pričakovanja stranke
Specifikacije Proces Produkt
Verifikacija
Validacija
Slika 4.2: Verifikacija in validacija
4.1 Testiranje modulov
Znotraj prve stopnje testiranja temeljito preverimo posamezne module. Moduli, ki jih
testiramo, so lahko razredi, skripte in drugi posamezni elementi, ki sestavljajo programsko
opremo. Glavna prednost testiranja modulov je v tem, da so preverjeni neodvisno od
drugih elementov v aplikaciji in je tako onemogočen zunanji vpliv na tega, ki ga testiramo.
Tako lahko hitreje in enostavneje lociramo problem, če ga najdemo na tej stopnji.
Ta testna stopnja je najbolj povezana z razvojem, saj dobimo module tako rekoč
naravnost izpod razvijalčevih rok. Za razvoj testov na tej stopnji moramo poznati
programski jezik, v katerem je modul napisan, ter seveda imeti izvorno kodo modula
samega. Predpostavimo, da testiramo naslednji modul oziroma funkcijo iz aplikacije
blagajna, ki nam vrne končno ceno z odštetim popustom [11].
-
Testiranje programske opreme
11
Izvorna koda 4.1: Funkcija odštej popust
double odstejPopust(double cena, int popustProc) {
if ((popustProc>0)&&(popustProc0.01)
testUspesen = false;
// testni primer 2
koncnaCena = pristejPopust(499.99,10);
if ((koncnaCena-449.99)>0.01)
testUspesen = false;
// testni primer x
// rezultat testa
return testUspesen;
}
Da preverimo, ali funkcija deluje in se obnaša pravilno, jo poganjamo z različnimi
vhodnimi podatki. Testno funkcijo lahko pohitrimo in poenostavimo tudi tako, da imamo
vhodne podatke in pričakovane rezultate v podatkovni bazi in kličemo testno funkcije v for
zanki. Najpogostejše napake, na katere naletimo, bodo napačni izračuni robnih primerov
-
Testiranje programske opreme
12
ter pozabljene poti programa, do katerih pride z napačnimi vhodnimi spremenljivkami. Na
te ne smemo pozabiti pri testiranju, saj je možno, da bo modul oziroma funkcijo, ki jo
testiramo, klical kateri drugi modul z napačnimi vhodnimi parametri. V tem primeru mora
funkcija vrniti dogovorjeno vrednost (v našem primeru vrne -1). To je samo eden izmed
primerov, ki mora biti pravilno obravnavan. Drugi takšni primeri pa so lahko na primer: ne
da se odpreti datoteke za pisanje, vrat na določenem IP-ju ipd… Če te izjeme niso
pravilno obravnavane, lahko pride do situacij, kjer dostopamo do kazalcev, ki kažejo na
napačne lokacije, deljenja z nič in napačnimi vrednostmi ter poskusov pisanja v datoteko,
ki je nismo odprli. V takih primerih se lahko aplikacija neha odzivati in se zruši, uporabnik
pa izgubi podatke.
Pri testiranju modulov preverjamo tudi njihovo učinkovitost in vzdržljivost. Učinkovitost
merimo tako, da gledamo porabo pomnilnika, časa, ki ga porabi algoritem za izračun, čas
dostopa do diskov, mreže, itd… Pri vzdržljivosti testiramo, kako težko je modul spreminjati
in mu dodajati nove funkcionalnosti. Ključnega pomena je, da razvijalec, ki bo te
spremembe dodajal, pozna in razume program. Če program popravlja razvijalec, ki ga je
napisal, ga seveda pozna in razume, kako deluje, medtem ko se mora nekdo, ki ni imel s
prvotnim razvojem nobenega stika, tega še naučiti. Vzdržljivost testiramo tako, da
preverimo strukturo kode, modularnost, kvaliteto, ustreznost in pogostost komentarjev v
kodi, upoštevanje standardov ter kvaliteto dokumentacije.
Če pri izdelavi testov in testnih primerov preizkuševalec pozna in upošteva strukture,
funkcije, spremenljivke in kodo, ki so v modulu, temu rečemo testiranje po principu bele
škatle. Najpogosteje uporabljen tip testiranja, je testiranje po principu črne škatle, kjer
preizkuševalec ne pozna oziroma se ne poglablja dosti v to, kako modul pride do
rezultata, ampak ga zanimajo samo vhodne spremenljivke in rezultati, ki jih mora z
izbranimi vhodnimi spremenljivkami dobiti. Najpogosteje ga uporabljamo zato, ker so
moduli oziroma komponente, ki jih testiramo, po navadi že sestavljeni iz drugih manjših
modulov in so preveliki oziroma preveč kompleksni, da bi iz kode lahko razbrali, kako
delujejo (za to bi porabili preveč časa). Dober pristop k razvoju je »test najprej« (angl.
test first development), kjer preden naredimo modul oziroma komponento, sprogramiramo
test za ta modul in šele nato gremo razvijati modul sam. Kodo modula izboljšujemo tako
dolgo, dokler ne prestane vseh testov. Temu pravimo test-driven development.
-
Testiranje programske opreme
13
4.2 Integracijsko testiranje
Pri integracijskem testiranju preverjamo, ali moduli oziroma komponente med seboj
pravilno komunicirajo. Predpostavimo, da razvijamo spletno trgovino ter da smo pri
zadnjih korakih nakupa, kjer vnesemo kupon, ki bi nam moral dati deset odstotkov
popusta na celoten nakup. Prikazano imamo, da nam je kupon vneslo uspešno, a popusta
nam ne upošteva ali pa se aplikacija celo neha odzivati. Pri testiranju modulov pa v
funkcijah dodajKupon, ki prebere vrednost kupona iz baze, in odstejPopust, ki izračuna
končno ceno z dodanim kuponom, nismo našli nobene napake ̶ problem je v
komunikaciji med njima. Cilj integracijskega testiranja je, da najdemo vse takšne napake
in konflikte med moduli v naši programski opremi. Do problemov lahko pride, ko imajo
vmesniki modulov nekompatibilne formate, kar se lahko zgodi zaradi napačnih specifikacij
ali pa če moduli niso narejeni po specifikacijah. Pri integracijskem testiranju najdemo tudi
napake v komunikaciji in izmenjavi podatkov med moduli. Ti se lahko odražajo, ko:
modul ne pošlje podatkov ali pa pošlje napačne podatke. Komponenta, ki bi
morala te podatke dobiti oziroma jih dobi, se preneha odzivati ali pa se zruši.
komunikacija med moduloma deluje pravilno, modula pa napačno interpretirata
poslane/prejete podatke (to se lahko zgodi zaradi napačnih specifikacij ali pa
zaradi napake v modulu).
so poslani pravilni podatki, a ne dovolj hitro ali pa ob napačnem času [11].
Obstajajo tudi komponente, ki jih pri testiranju modulov ne moremo preveriti – na primer
podatkovno bazo nekega tretjega proizvajalca, v kateri imamo shranjene podatke.
Delovanje takšnih komponent preverimo pri integracijskem testiranju, ko so povezane z
našimi moduli. Tudi v tej stopnji testiranja potrebujemo testne funkcije, uporabimo pa
lahko tiste, ki smo jih naredili pri testiranju modulov. Med testiranjem lahko uporabimo
orodja, ki spremljajo promet med komponentami. Eno izmed takšnih orodij je program
Wireshark, ki spremlja promet na omrežju.
Integracijskega testiranja se lahko lotimo z različnimi strategijami:
Top-down integracija:
Testiranje začnemo z najvišjim modulom, ki kliče oziroma uporablja druge module,
njega samega pa ne kliče noben drug modul. Prednost te strategije je, da ne
potrebujemo testnih funkcij, saj že imamo vmesnik za testiranje nižjih modulov.
-
Testiranje programske opreme
14
Slabost pa je v tem, da moramo uporabiti t. i. nastavke (angl. stubs) za module, ki
še niso bili razviti.
Bottom-up integracija:
Testiramo od spodaj navzgor. Začnemo z modulom, ki ne kliče nobenega drugega
modula (razen mogoče sistemskih modulov). Dobra lastnost te strategije je v tem,
da ne potrebujemo nastavkov, slabost pa da rabimo testne funkcije, ki simulirajo
module višjih stopenj, ki še niso razviti.
Ad hoc integracija:
Testiramo v istem vrstnem redu, kot so moduli razviti. S to strategijo prihranimo
dosti časa, slabost pa je v tem, da potrebujemo oboje ̶ nastavke in testne
funkcije.
Backbone integracija:
Zgradimo ogrodje in dodajamo komponente oziroma module postopoma. Module
lahko dodajamo v kakršnem koli vrstnem redu, moramo pa ustvariti ogrodje, kar ni
tako enostavno in tudi vzame precej časa.
Big bang integracija:
To je najslabša možnost – integracijsko testiranje začnemo, ko so vsi moduli
razviti in povezani v celoto. S tem izgubimo dosti časa med razvojem aplikacije,
saj bi lahko testirali in našli več napak med posameznimi moduli, preden je razvoj
drugih sploh končan. Ko naletimo na napako, jo je težje tudi najti v izvorni kodi, ter
popraviti [11].
Katera strategija je najboljša, je odvisno od projekta do projekta. Za njo se odločimo na
podlagi tega, koliko in kakšne module imamo ter kako so odvisni drug od drugega.
Odvisno je tudi od projektnega načrta – kdaj bodo kateri moduli razviti in na voljo za
testiranje. Pri izdelavi načrta je dobro, da je zraven vodja preizkuševalcev, ki poda svoje
mnenje glede vrstnega reda razvoja. Na koncu moramo upoštevati še testni plan, v
katerem imamo določeno, kaj vse, kako podrobno ter koliko časa bomo testirali.
4.3 Sistemsko testiranje
Po integracijskem testiranju preidemo na sistemsko testiranje, v katerem preverimo, ali
produkt (sedaj že sestavljen v celoti) dosega cilje, dogovorjene v specifikaciji. Pri
sistemskem testiranju ne potrebujemo več testnih funkcij in nastavkov, ampak moramo
-
Testiranje programske opreme
15
aplikacijo testirati kot celoto na testni platformi ̶ to je na strojni in programski opremi
(operacijskem sistemu, s specifičnimi gonilniki, drugimi aplikacijami itd.). Testna platforma
mora biti enaka oziroma čim bolj podobna sistemu, na katerem bo program tekel. Na
dejanskem produkcijskem sistemu, kjer bo produkt uporabljen, ni priporočljivo testirati, saj
lahko pokvarimo delovno okolje, če pride do kakšne napake, na njem pa verjetno tečejo
še kakšne druge aplikacije, ki so kritične v delovnem procesu. Drug razlog je to, da ne
vemo, katere aplikacije stranka poganja, kaj te aplikacije delajo, in se zaradi tega lahko
okolje spreminja med samim testom oziroma med več testi. V takšnih primerih bi lahko v
enem testu prišlo do neke napake, ko pa bi hoteli test ponoviti, se ta ne bi pojavila.
Pri sistemskem testiranju preverimo tudi, kako optimizirati sistem, da bo naš program
tekel karseda hitro. V tej stopnji poganjamo tudi teste, v katerih preizkusimo zmogljivosti
(angl. performance testing), ter pregledamo vso dokumentacijo [11].
4.4 Testiranje sprejemljivosti
Preden lahko aplikacijo dokončno izdamo, je dobro, da jo preizkusi še nekaj bodočih
uporabnikov. Ti testi se lahko opravijo tudi na nižjih nivojih:
Komercialnim produktom lahko preverimo sprejemljivost med integracijskim
testiranjem.
Sprejemljivost posameznih komponent se lahko preveri med testiranjem modulov
oziroma komponent.
Nove funkcionalnosti so lahko testirane na prototipih pred sistemskim testiranjem.
Koliko časa namenimo testiranju sprejemljivosti, je odvisno od tveganja. Za izdelke
namenjene specifični stranki je tveganje visoko in so potrebni bolj podrobni testi, kot pri
aplikaciji, ki je namenjena množicam ljudi. Pri testiranju si lahko oseba, ki testira, pomaga
z dokumenti, ki so bili narejeni med razvojem aplikacije, kot so na primer: navodila za
uporabo, specifikacije, zahteve, poročila itd.
Pri tem testiranju se največ posvečamo validaciji. Cilj tega testiranja je, da stranka pridobi
zaupanje v aplikacijo oziroma sistem. Poznamo več vrst testiranja sprejemljivosti:
uporabniško testiranje sprejemljivosti, operativno testiranje, in testiranje pogodbenih
sprejemljivosti [11].
-
Testiranje programske opreme
16
4.4.1 Uporabniško testiranje sprejemljivosti
To strategijo uporabimo, ko naročnik in uporabnik nista ena in ista oseba, saj ima včasih
uporabnik, ki bo produkt uporabljal, drugačna pričakovanja kot naročnik, ki je programsko
opremo naročil. Aplikacijo morajo preveriti vsi uporabniki, ki jo bodo uporabljali, saj lahko v
tej fazi ugotovijo, da je program, ne glede na to, da deluje pravilno,za to, kar je namenjen,
prezahteven ali preokoren. V mislih imajo po vsej verjetnosti uporabniški vmesnik, ki je
lahko po njihovem mnenju preveč okoren, neroden ali nelogičen. Na tej stopnji razvoja v
uporabniškem vmesniku še lahko naredimo manjše popravke, a za večje spremembe je
po navadi že prepozno. Da se teh problemov rešimo, je dobro, da bodoči uporabniki
preverijo prototipe aplikacije v zgodnji fazi razvoja [11].
4.4.2 Operativno testiranje
Operativno testiranje opravijo sistemski administratorji in vključuje testiranje ustvarjanja in
nalaganja varnostnih kopij (nastavitev, podatkovnih baz itd.) ter preverjanje upravljanja z
uporabniki in raziskovanja varnostnih pomanjkljivosti v programski opremi.
4.4.3 Testiranje pogodbenih sprejemljivosti
Ta strategija je na voljo v primeru, ko je programska oprema razvita za specifičnega
uporabnika. Programsko opremo primerja s kriteriji, določenimi v pogodbi, in preveri, da ni
večjih napak v njej. Testni in sprejemljivostni kriteriji morajo biti določeni kolikor se da
točno in ne smejo biti dvoumni. Preden začne uporabnik preverjati sprejemljivost v svojem
testnem okolju, ki mora biti čim bolj podobno produkcijskemu, gremo skozi iste teste tudi
sami v svojih testnih okoljih. Zelo pomembno je, da se pred testiranjem dogovorimo o
testnih primerih z uporabniki, da ne pride do nesporazumov pri razumevanju potrebnih
sprejemljivosti [11].
-
Testiranje programske opreme
17
4.5 Alpha testiranje
Tega opravimo pred koncem razvoja programske opreme znotraj podjetja, kjer jo
razvijamo. V prvi fazi alpha testiranja programsko opremo preverjajo razvijalci, ki za to
uporabijo razhroščevalnike. V drugi fazi pa pridemo na vrsto preizkuševalci in drugi, ki
smo zadolženi za zagotavljanje kakovosti in programsko opremo pregledamo v okolju, ki
je čim bolj podobno produkcijskemu.
Lahko pa se poslužimo tudi tako imenovanega testiranja pasje hrane, kjer razdelimo
aplikacijo oziroma sistem zaposlenim v podjetju in jo nekaj časa uporabljamo. Take
tehnike se poslužujeta tako Microsoft kot Google [11].
4.6 Beta testiranje
Pri beta testiranju pošljemo aplikacijo strankam, ki jo testirajo tako, da jo poganjajo v
okolju, v katerem bo tekel končni produkt. Cilj beta testov je, da aplikacijo preizkusijo
ljudje, ki jo bodo dejansko uporabljali. Poznamo odprte in zaprte beta teste. Pri zaprtih
damo aplikacijo določenim uporabnikom v testiranje, v odprtem pa je aplikacija na voljo
vsem. Glavna prednost beta testiranja je v tem, da uporabniki naletijo na situacije, na
katere nismo niti pomislili, in če naletijo v takšnih primerih na napake, jih lahko popravimo
preden izdamo končno različico aplikacije.
4.7 Testiranje novih verzij in popravkov
Z izdajo programske opreme seveda z razvojem nismo končali, saj je to samo en del
življenjskega cikla programske opreme. Le-to moramo po izdaji vzdrževati (oziroma je ni
treba, če nam ni mar za stranke in želimo hitro priti na slab glas). Priporočljivo je, da
imamo dve strategiji: eno za kritične popravke in eno za načrtovane posodobitve [11]. Pri
izdaji kritičnih popravkov je pomembna hitrost, zato po navadi preverimo samo popravek
in nekaj manjših povezanih in pomembnih funkcij pred njihovo izdajo, po izdaji pa
preverimo program bolj podrobno. Pri načrtovanih posodobitvah, ki so planirane naprej,
moramo upoštevati tudi bolj natančno testiranje, pri katerem moramo preveriti vse nove
funkcije in funkcije, ki so povezane z njimi, ter delovanje posodobitev samih, kot so na
-
Testiranje programske opreme
18
primer podatki v podatkovni bazi. Priporočljivo je, da se preverijo tudi vsi ostali moduli
oziroma funkcije. Temu pravimo regresijsko testiranje.
-
Testiranje programske opreme
19
5 TIPI TESTIRANJA
5.1 Funkcionalno testiranje
Funkcionalno testiranje je, kot nam ime pove, testiranje funkcij v modulih, komponentah in
sistemu. Pri tem testiranju nas zanima, ali funkcija, ki jo preverjamo, deluje pravilno. To
lahko naredimo na dva načina:
S testiranjem osnovanim na zahtevah, pri katerem razvrstimo dogovorjene
zahteve glede na stopnjo tveganja, in na podlagi tega poganjamo teste. To nam
omogoča, da najprej preverimo najpomembnejše dele v programski opremi, da so
lahko čim hitreje popravljeni.
Testiranje osnovano na delovnem procesu pa poteka tako, da testiramo na
enak način, kot bo aplikacija uporabljena. Če testiramo aplikacijo blagajna, je
proces takšen, da skeniramo izdelke, dodamo kupon oziroma popust, izberemo
način plačila in izvedemo plačilo. Pri tem načinu moramo preizkuševalci poznati
proces, ki bo uporabljen pri uporabi programa, ki ga razvijamo [11].
5.2 Nefunkcionalno testiranje
Pri nefunkcionalnem testiranju preverjamo zmogljivost in kvaliteto modulov oziroma
komponent. Nefunkcionalno testiranje je sestavljeno iz:
Testiranja funkcionalnosti, pri katerem preverimo, ali program naredi to, kar
mora, in je tako tudi dogovorjeno v specifikaciji. Med testiranjem preverimo glavne
funkcije, menije ter delovanje namestitvenega programa.
Testiranja zanesljivosti, pri katerem preverimo, ali je program med normalno
rabo stabilen.
Testiranja uporabnosti, pri katerem preverimo, ali sta aplikacija in njen
uporabniški vmesnik dovolj enostavna za uporabo. To preverimo s petimi kriteriji:
o Učljivost: Raziščemo, kako hitro uporabniki, ki prvič vidijo program, nekaj
naredijo – dosežejo nek cilj.
o Učinkovitost: Raziščemo, koliko časa uporabniki potrebujejo za izpolnitev
neke naloge.
-
Testiranje programske opreme
20
o Pomnljivost: Preverimo, ali aplikacijo uporabnik potem, ko je nekaj časa
ne uporablja, prepozna takoj in dela z njo s takšno hitrostjo kot prej, ali pa
je potreben čas, da se je uporabnik zopet navadi.
o Napake: Preverimo, koliko ter kakšne so napake, ki jih naredijo uporabniki,
ter kako hitro jih lahko odpravijo.
o Zadovoljstvo: Preverimo, ali uporabnik rad uporablja program.
Testiranja učinkovitosti, pri katerem preverimo koliko kode in testiranja je
potrebno za izvedbo posamezne funkcionalnosti. Količino testiranja ovrednotimo
tako, da vzamemo število testnih primerov in ga delimo s časom, ki je potreben za
njihovo izvedbo.
Testiranja vzdrževanja, kjer preverimo, kako enostavno je aplikacijo vzdrževati.
To ocenimo tako, da preverimo, kako enostavno je aplikacijo analizirati, spremeniti
in ponovno testirati.
Testiranja prenosljivosti, pri katerem preverimo, kako enostavno lahko aplikacijo
spremenimo, da bo delala na drugem operacijskem sistemu– npr. iz Debian 5 na
Debian 7 ali pa iz Windows 7 na Windows 10. To merimo s časom, ki je potreben
za spremembo, in časom potrebnim za posodobitev dokumentacije.
Izhodiščnega testiranja, pri katerem moramo oceniti dokumente in specifikacije s
katerimi bomo zasnovali testne primere. Validaciji zahtev in specifikacij imenujemo
tudi testiranje izhodišč.
Testiranja skladnosti, kjer preverimo, ali je programska oprema, ki jo razvijamo
dovolj kvalitetna in dosega standarde našega podjetja.
Testiranja dokumentacije, pri katerem preverimo navodila za uporabo,
specifikacije, načrte za testiranje, dnevnike testiranja, rezultate testiranja …
Testiranja vzdržljivosti, kjer obremenimo naš program za določen čas in
beležimo, kako se obnaša. Pri tem testiranju lahko odkrijemo t. i. memory leaks, ki
jih prej, ko smo program uporabljali krajši čas, nismo opazili.
Testiranja obremenitve, kjer preverimo, kako se sistem obnaša pod določeno
obremenitvijo. Tukaj ugotovimo največjo obremenitev, ki jo naša programska
oprema zmore – npr. koliko uporabnikov lahko program uporablja naenkrat, koliko
elementov se lahko doda, simulira ipd. Te rezultate si seveda zapišemo, da jih
lahko posredujemo zainteresiranim strankam.
Testiranja zmogljivosti, pri katerem preverimo, kako hitro aplikacija ali del
aplikacije deluje. Ko imamo rezultate, jih lahko primerjamo z drugimi
-
Testiranje programske opreme
21
konkurenčnimi aplikacijami in vidimo, ali je naša aplikacija hitrejša. Lahko pa tudi
odkrijemo funkcije, ki upočasnjujejo celotno aplikacijo in jih potem popravimo.
Testiranja združljivosti, pri katerem testiramo, ali je aplikacija kompatibilna s
strojno opremo, operacijskim sistemom, podatkovno bazo in drugimi programi.
Testiranja varnosti, kjer preverimo varnost aplikacije – če lahko do podatkov
dostopajo nepooblaščeni uporabniki, je možno zaobiti prijavo itn.
Testiranja razširljivosti, kjer preverimo, kako lahko povečamo zmogljivost naše
aplikacije (število uporabnikov, dodanih objektov …).
Testiranja pod obremenitvijo, pri katerem aplikacijo obremenimo nad njeno
zmogljivostjo in opazujemo, kaj se v takšnem primeru dogaja. S tem ugotovimo
stabilnost našega programa, kako se obnaša v takšnih primerih in kako se odziva
na napake. Cilj testiranja je, da zagotovimo, da program deluje pravilno tudi, če
zmanjka sistemskih virov (pomnilnika, prostora na trdem disku itd.).
Testiranje okrevanja, kjer preverimo, kako hitro in dobro aplikacija okreva po
napakah. Napake moramo sprožati sami na več različnih načinov – npr. med
prenašanjem podatkov po mreži odstranimo UTP-kabel (mrežni kabel) ter ga čez
nekaj trenutkov vstavimo nazaj.
Pri testiranju lokalizacije preverimo, kako se naša programska oprema obnaša
pri različnih regijskih nastavitvah – ali je prikaz datuma in ure pravilen ali lahko
vnašamo podatke z drugimi znaki (npr. šumniki, kitajske pismenke, cirilica …) [16].
5.3 Regresijsko testiranje
Regresijsko testiranje je testiranje programske opreme, ki smo jo spremenili, ko smo
popravili hrošče, dodali nove funkcionalnosti itn. Testirati jo moramo ponovno, da
ugotovimo, ali so hrošči res odstranjeni, če nove funkcionalnosti delujejo pravilno in brez
napak ter da nismo pridelali novih hroščev oziroma s popravkom odkrili skrite hrošče.
Regresijsko testiranje lahko opravljamo na vseh stopnjah testiranja in uporabimo testne
primere prvotnega testiranja. Testiramo lahko bolj ali manj obsežno, odvisno od časa, ki
ga imamo na voljo:
Ponovno poženemo vse teste, pri katerih smo odkrili napake, ki so bile
odpravljene.
Preverimo samo tiste dele programa, ki so bili spremenjeni ali popravljeni.
Preverimo samo nove funkcionalnosti.
-
Testiranje programske opreme
22
Testiramo vse (popoln regresijski test) [11].
Če celotne aplikacije ne preverimo še enkrat, se lahko zgodi, da funkcionalnosti, ki so prej
delovale, sedaj ne delujejo več, zato je priporočljivo, da to naredimo še enkrat. Takšno
preverjanje pa je velikokrat preveč časovno zahtevno, zato se tega lotimo tako, da:
ponovimo samo teste, ki imajo visoko prioriteto v testnem načrtu,
izpustimo določene testne primere (npr. pri testiranju funkcije odstejPopust
poženemo test samo enkrat z izbranim testnim primerom, drugih testnih primerov
ne poganjamo),
omejimo testiranje: testiramo samo na eni podprti platformi, v samo enem jeziku
itd.,
testiramo samo določene funkcije, oziroma funkcionalnosti [11].
5.4 Statično testiranje
Pri statičnem testiranju za razliko od dinamičnega testiranja, aplikacije oziroma modula ne
poganjamo ampak ga analiziramo. Poleg same aplikacije lahko analiziramo tudi druge
dokumente pomembne za razvoj in uporabo produkta, kot so na primer navodila za
uporabo. Pri statičnem testiranju najdemo odstopanja od projektnega načrta, standardov
in specifikacij, manjkajoče zahteve, kodo, ki jo je težko vzdrževati, in nepravilne vhodne in
izhodne spremenljivke v modulih. Če napake in odstopanja najdemo dovolj hitro, jih
enostavneje in hitreje odpravimo, kot če bi jih našli proti koncu in bi morali velik del
programa predelati na novo. Tako lahko skrajšamo čas razvoja s tem, da nekaj časa
porabimo za statično testiranje. Poznamo več načinov statičnega testiranja: pregled
(angl. reviews) in statična analiza [11].
5.4.1 Pregled
Pri pregledu preverjamo dokumente oziroma kodo, ki jo testiramo. Najbolje je, da pregled
opravimo po zaključku vsake faze razvoja, da čim hitreje najdemo napake. Naš cilj mora
biti izboljšava dokumenta oziroma kode in ne kritiziranje avtorja, saj lahko s tem uničimo
njegovo motivacijo ter ga postavimo v obrambni položaj. To se zgodi predvsem, če se
osredotočamo na njegove napake in ne na to, kako bi lahko dokument oziroma kodo
izboljšali.
-
Testiranje programske opreme
23
Pregled poteka po naslednjem postopku: Vodje projekta se odločijo, katere dokumente
bomo pregledali, kako jih bomo pregledali ter koliko časa bomo imeli na voljo. Določijo
ustrezne ljudi, ki bodo poleg avtorja dokumenta sodelovali pri posameznem pregledu
(Pregled je uspešnejši, najdemo tudi več napak, če dokument preverjajo ljudje, ki imajo
nanj različne poglede oziroma stališča.) ter preverijo ali je dokument pripravljen. Če
nimamo dovolj časa za pregled celotnega dokumenta, se določijo najbolj kritični deli in
pregledamo samo te. Nadaljujemo s predogledom, kjer člani, ki bodo pregledovali
dokument, delijo informacije o dokumentu, ki ga bodo pregledali. Če kdo ni seznanjen s
področjem, ki ga aplikacija pokriva, ga s tem seznanimo. Naslednja stopnja je
individualna priprava, kjer se mora vsak član ekipe pripraviti na sestanek, ki je mogoč
samo takrat, ko so vsi člani dovolj pripravljeni. Pripravimo se tako, da pregledamo
dokument ter ga primerjamo s specifikacijami. Vsako odstopanje, predlog, vprašanje si
zapišemo. Nato je na vrsti pregledni sestanek (angl. review meeting), ki ga vodi vodja
pregleda ali pa moderator. Moderator poskrbi, da vsak pove svoje mnenje ter da se
ocenjuje produkt (dokument, kodo …) in ne njegovega avtorja. Pregledovalci moramo
paziti, da ne obtožujemo avtorja, on pa, da ne brani sebe in dokumenta. Priporočljivo je,
da avtor razloži svoje mišljenje oziroma odločitve. Sestanek naj ne bi trajal več kot dve uri
in ga lahko vodja odpove, če je kakšen član odsoten ali pa se ni dovolj pripravil. Vsak
pregledovalec naj ima dovolj časa, da predstavi svoje rezultate. Objekte v dokumentu
ovrednotimo na:
Kritične napake, ki morajo biti odpravljene preden je dokument odobren.
Večje napake, zaradi katerih trpi uporabnost dokumenta in morajo biti odpravljene
pred odobritvijo dokumenta.
Manjše napake, kot so na primer napačno črkovanje, nerodno izražanje, ki zelo
malo vplivajo na uporabnost.
Brez napake – ti deli so brez napake in se ne smejo spremeniti pri predelavi
dokumenta [11].
Na koncu sestanka se odločimo, ali je dokument prestal pregled ter kako naprej. Če
dokument ni odobren, ga mora avtor predelati, po predelavi pa ga je potrebno ponovno
pregledati. Če je bilo treba popraviti samo nekaj manjših napak, pregleda popravljen
dokument vodja ali moderator. Če pa so bile napake velike, je potrebno dokument
pregledati ponovno (običajno samo popravke in ne celotnega dokumenta) in sklicati
sestanek, na katerem se odločimo ali so popravki sprejemljivi.
-
Testiranje programske opreme
24
Poznamo več vrst pregledov:
Prehod (angl. walkthrough) je neformalni pregled dokumentov, kot so na primer navodila
za uporabo, specifikacije itd. Priprava na sestanek je minimalna, včasih celo ni
potrebna, sestanek sam pa vodi avtor dokumenta, ki ga pregledujemo. Na sestanku
skupaj pregledamo dokument in iščemo napake ter podajamo ideje, kako bi ga
izboljšali. Glavni cilj je spoznavanje in razumevanje produkta ter iskanje napak [11].
Pri tehnični pregledu (angl. technical review) se osredotočimo na to, da je dokument
skladen s specifikacijami in standardi ter da produkt naredi to, za kar je namenjen.
Tehnični pregled opravljajo ljudje s tehničnim znanjem, ki za osnovo uporabijo uradne
specifikacije in kriterije. Med pripravo si zapišejo svoja opažanja in komentarje in jih
oddajo moderatorju pred sestankom, ta pa se odloči, kateri so najbolj pomembni. O
teh problemih se razpravlja na sestanku. Pri tehničnem pregledu se razišče
alternativne pristope ter se razrešijo tehnična vprašanja. Občasno se najdejo tudi
kakšne napake [11].
Inšpekcija (angl. inspection) je formalni proces, ki poteka po vnaprej določenih korakih.
Vsak, ki sodeluje, ima določeno vlogo in se mora dobro pripraviti na sestanek
(temeljito pregleda dokument oziroma del dokumenta, ki je bil določen njemu), ki ga
vodi izkušen moderator. Pri inšpekciji sodelujejo avtor ter njegovi vrstniki – kolegi iz
istega področja. Zaželeno je, da nekaj vrstnikov, ki sodelujejo pri pregledu ni delalo na
projektu in tako dobimo mnenje oseb, ki se prvič srečajo s produktom oziroma
dokumentom. Le-ti lahko najdejo napake, ki bi jih vsi sodelujoči pri projektu
spregledali (projektna slepota). Inšpekcijo po navadi izvajamo na dokumentih s
programsko kodo, lahko pa se uporabi tudi na drugih dokumentih. Najdene napake si
zapišemo v dnevnik oziroma seznam. Cilj inšpekcije je, da najdemo čim več napak ter
tako izboljšamo kvaliteto produkta. Cilj je tudi, da se avtor uči iz odkritih napak, tako
jih bo kasneje, pri nadaljnjem delu, naredil manj[11].
5.4.2 Statična analiza
Statična analiza se opravi s pomočjo za to namenjenih aplikacij in jo po navadi izvajamo
med testiranjem modulov ali pa med integracijskim testiranjem. Tudi prevajalnik je orodje
za statično analizo, saj preverja sintakso, primerja tipe podatkovnih struktur, ki jih med
seboj uporabljamo (npr. primerja tip vrednosti, ki ga funkcija vrne s tipom spremenljivke, v
katero želimo to vrednost shraniti), najde spremenljivke, ki jih nikoli ne uporabimo itd. Z
-
Testiranje programske opreme
25
drugimi orodji pa analiziramo tudi, ali naša koda ustreza standardom kodiranja, ki
določajo, kako naj poimenujemo spremenljivke, razrede ipd.. Analiziramo tudi
kompleksnost kode, ki nam kaže, kako razumljiva ali enostavna je koda, tako da nam
izračuna, kolikšna je globina gnezdenja ali pa izračuna kompleksnost glede na to, koliko
binarnih odločitev vsebuje. Z orodji preverimo tudi strukturo kode – v kakšnem vrstnem
redu se izvajajo ukazi, po kakšni poti potujejo podatki ter kako so podatki, ki jih program
uporablja, organizirani (npr. v podatkovni bazi, datotekah na disku …).
5.5 Dinamično testiranje
Pri dinamičnem testiranju kodo poganjamo z izbranimi testnimi podatki in primerjamo
dobljen rezultat s pričakovanim. Priporočljivo je, da pričakovane rezultate pridobimo in
izračunamo preden gremo poganjati teste, saj lahko v nasprotnem primeru rezultat, ki ga
dobimo, vpliva na izračun pričakovanega rezultata. Pri testiranju modulov in
integracijskem testiranju velikokrat ne moremo testirati posameznih elementov posebej,
zato jih moramo povezati v testnem okolju (Slika 5.1), ki vsebuje objekt, ki ga testiramo,
ter funkcije, ki jih naš objekt kliče oziroma nastavke na funkcije, ki še niso bile
implementirane. Z nastavki simuliramo obnašanje teh funkcij [11].
Testni objekt
Testni primer 1 ... Testni primer n
Funkcija 1
Vrnjen
rezultat
Funkcija 2
Nastavek funkcije 3
…
Nastavek funkcije n
Izvajalno okolje, orodja za
analizo, nadzorovanje
Primerjanje s
pričakovanim
rezultatom
Slika 5.1: Testno okolje
Prihranimo lahko veliko časa, če teste med seboj povezujemo (Rezultat, ki ga dobimo po
prvem testu, uporabimo kot vhodne spremenljivke za drug test.). Poskrbeti moramo tudi
za sledljivost – s katerim testom in njegovimi testnimi primeri smo preverili kateri element,
-
Testiranje programske opreme
26
opisan v specifikaciji. To nam pomaga pri ocenitvi, kako daleč smo s testiranjem ter tako
lažje in hitreje najdemo test in ga spremenimo, če se spremeni specifikacija. Dinamično
testiranje lahko opravimo z različnimi pristopi: s pristopom črne škatle, s pristopom bele
škatle, poleg točno določenih strukturiranih testov pa lahko testiramo tudi intuitivno.
5.5.1 Pristop črne škatle
Pri testiranju s pristopom črne škatle ne vemo oziroma nas ne zanima, kaj se znotraj
testnega objekta dogaja. Testni objekt sprejme testne spremenljivke oziroma podatke in
nam vrne rezultat določenega tipa. Na test lahko vplivamo samo z ustreznimi vhodnimi
spremenljivkami. Temu pristopu rečemo tudi funkcionalni pristop ali pristop osnovan na
specifikacijah, saj je namenjen testiranju funkcionalnosti in skladnosti s specifikacijami.
5.5.2 Pristop bele škatle
Pri uporabi pristopa bele škatle pri testiranju vidimo, kaj se znotraj testiranega objekta
dogaja ter lahko vplivamo na delovanje objekta v posebnih situacijah, kot so na primer
testni primeri, katere ne bi mogli izvesti s spreminjanjem vhodnih spremenljivk. Pri
načrtovanju testnih primerov poznamo strukturo objekta, glavni cilj pristopa bele škatle pa
je, da dosežemo določeno pokritost testiranja (na primer: koliko % kode v testnem
objektu je bilo izvedeno najmanj enkrat). Ta pristop se največkrat uporablja pri testiranju
modulov.
5.5.3 Intuitivno testiranje
Ta pristop temelji na izkušnjah in znanju preizkuševalcev. Pri njem se največkrat
odločimo, da bomo začeli testirati tiste dele programske opreme, kjer je bilo v preteklosti
največ napak, ter dele, kjer preizkuševalci menimo, da bo najverjetneje prišlo do njih.
Takšnemu izdelovanju testnih primerov pravimo tudi ugibanje napak in je velikokrat
uporabljeno. Ena izmed tehnik intuitivnega testiranja je raziskovalno testiranje, ki je
uspešno tudi v primerih, ko so specifikacije in dokumentacija slabo napisane ali pa celo ne
obstajajo. Pri raziskovalnem testiranju testov in testnih primerov vnaprej ne načrtujemo
-
Testiranje programske opreme
27
ampak aplikacijo (ali pa njen del) preletimo in se odločimo, katere funkcionalnosti bomo
preverili. Preverimo z nekaj testnimi primeri in se na podlagi rezultatov odločimo, kako
bomo s testiranjem nadaljevali – kaj bomo preverili v naslednjem koraku. S tem
nadaljujemo in tako dobimo predstavo, kako bi moral objekt delovati, vmes pa beležimo
in poročamo o napakah ter odstopanjih na katere smo naleteli.
-
Testiranje programske opreme
28
6 AVTOMATIZACIJA TESTIRANJA
Pri testiranju programske opreme si lahko pomagamo z orodji, nekateri testi pa so lahko v
celoti avtomatizirani. Avtomatizacija testiranja programske opreme ima kar nekaj
prednosti:
Zmanjševanje ponavljajočega dela: če v nekem testu uporabimo določene
korake, ki so vedno enaki, postane izvajanje le-tega zelo dolgočasno. V takšnih
primerih se nam rado pripeti, da delamo napake. Pod to spadajo regresijski testi,
vnašanje testnih podatkov …
Boljša ponovljivost: čeprav dostikrat mislimo, da ko neko stvar ponavljamo, jo
naredimo vedno enako, jo po navadi naredimo na malo drugačen način. Orodja, ki
jih uporabimo pri testiranju pa dejansko ponovijo neko stvar tako, kot so jo v
prejšnjem koraku.
Objektivnost: programska oprema bo 100% objektivna pri interpretiranju
pridobljenih podatkov, medtem ko človek lahko te podatke interpretira narobe.
Boljši prikaz informacij: ljudje lažje razumemo informacije, ki so nam prikazane v
diagramih, kot na primer gole podatke. Orodja za testiranje nam te podatke lahko
takoj pokažejo v grafih. (V programu, ki ga bomo razvili, bomo prikazovali porabo
pomnilnika želene aplikacije v grafu – gole podatke bo uporabnik lahko videl samo,
če bo to specifično želel.) [14].
Posebej moramo biti pazljivi, da se ne navadimo in ne zanašamo preveč na orodja, saj v
nekaterih primerih avtomatizacija ni smiselna (Če bi potrebovali preveč časa, da bi test
avtomatizirali, ne bi pa ga velikokrat poganjali.). Izračunati moramo tudi celoten čas, ki je
potreben, da vpeljemo neko orodje v proces testiranja – poleg nakupa orodja se ga
morajo preizkuševalci tudi naučiti uporabljati. Vprašamo se tudi, če rezultati, ki jih bomo
pridobili, odtehtajo ceno orodja (Vključno s časom, ki je potreben, da se ga naučimo
uporabljati.) [15].
Na voljo imamo veliko tipov aplikacij namenjenih testiranju. Nekatere izmed njih se
uporabljajo za dinamično analizo kode, ki se je večinoma poslužujejo razvijalci, da najdejo
napake v kazalcih, osipe pomnilnika in časovne odvisnosti. Druge lahko uporabimo za
testiranje zmogljivosti – odzivnih časov, pretoka podatkov itn.
Obstajajo tudi aplikacije, s katerimi lahko avtomatiziramo testiranje uporabniških
vmesnikov. V njih posnamemo korake, ki naj jih aplikacija izvede za testiranje, in
-
Testiranje programske opreme
29
rezultate, ki bi jih morali dobiti. Takšne aplikacije imajo tudi veliko hibo – ko se kakšen
element v uporabniškem vmesniku spremeni (npr. doda gumb v orodni vrstici), je
potrebno teste zgraditi (posneti) ponovno.
V tej diplomski nalogi bomo naredili orodje, ki bo prišlo prav pri sistemskem testiranju.
Orodje bo spremljalo porabo pomnilnika izbrane aplikacije ter prikazovalo rezultate na
grafu. Podatki sami se bodo shranjevali v podatkovno bazo in/ali datoteko z vrednostmi
ločenimi z vejico (CSV-datoteka), lahko pa bomo tudi videli gole podatke. Z orodjem bomo
tako lahko zaznali osipe pomnilnika v končni aplikaciji ter med obremenitvenimi in
zmogljivostnimi testi avtomatizirali proces spremljanja porabe pomnilnika.
-
Testiranje programske opreme
30
7 DOKUMENTIRANJE TESTIRANJA IN JAVLJANJE HROŠČEV
Pri testiranju pridelamo veliko dokumentov, kot so:
Testni načrt, ki vsebuje cilje, seznam oseb, ki bodo vključene pri testiranju, načrt,
kaj se bo testiralo in kako, ter testno strategijo.
Tabela sledljivosti, v kateri povežemo zahteve s testi, s katerimi preverimo, ali je
določena zahteva izpolnjena.
Testni primeri, ki vsebujejo določene korake, po katerih test poteka, vhodne
spremenljivke, ki bodo uporabljene ter pričakovani rezultat. Zbirki testnih primerov
rečemo testna zbirka.
Skripte in orodja, ki smo jih pridelali in/ali uporabili pri testiranju naše aplikacije.
Ko pri testiranju naletimo na napako, jo seveda dokumentiramo v t. i. bug reportu oziroma
poročilu o hrošču, ki mora vsebovati dovolj informacij, da lahko razvijalec napako ponovi,
razišče in jo v kodi najde ter odpravi. Zato je pomembno, da so naša poročila o hroščih
kvalitetna – da so nedvoumna ter da vsebujejo vse pomembne informacije, ki jih bo
razvijalec potreboval. Osnovni elementi poročila o hrošču, na katere moramo biti pozorni
so:
Naslov, v katerem naj bo razvidno, kakšna je napaka. Dober naslov se od slabega
razlikuje v tem, da je iz njega točno razvidno, v čem je problem, medtem ko je slab naslov
preveč splošen in razvijalcu ne pove kaj dosti. Na primer:
Slab naslov:
Dodajanje vrednosti ne deluje pravilno
Dober naslov:
Dodajajo se lahko samo celoštevilske vrednosti - ne gre dodati števila z decimalno vejico
Testno okolje, v katerem smo opazili napako, mora biti natančno opisano, saj je možno,
da se v drugačnem testnem okolju napaka ne ponovi. Točno moramo javiti, kakšna je
strojna oprema, na kateri smo testirali, na katerem operacijskem sistemu smo testirali, ali
je operacijski sistem posodobljen ali ne ter ali imamo poleg aplikacije, ki jo testiramo,
nameščene še kakšne druge, kakšne so nastavitve v naši aplikaciji …
-
Testiranje programske opreme
31
Koraki za reproduciranje, ki naj vsebujejo zaporedno oštevilčene korake, ki so potrebni,
da ponovimo napako. Koraki naj bojo enostavni in točni. Število korakov lahko zmanjšamo
tako, da združimo nekatere pogosto uporabljene korake, kot je na primer: Uporabnik naj
bo prijavljen v sistem, namesto da celoten postopek prijave vsakič opišemo po korakih
(Nekje pa seveda moramo imeti zapisane posamezne korake, ki jih za prijavo
uporabimo.). Priporočljivo je tudi, da ko korake zapišemo, še enkrat reproduciramo
napako, tako da uporabimo korak za korakom. Te korake zapišemo preden oddamo
poročilo, da se prepričamo, da nismo ničesar izpustili in da se napaka res ponovi.
Nato opišemo pričakovane in dobljene rezultate. Pričakovane rezultate opišemo tako,
da javimo, kaj bi se moralo zgoditi in ne kaj se ne bi smelo. Enako velja za dobljene
rezultate – napišemo, kaj se je zgodilo, ne kaj se ni. Na primer: namesto »Okno se ne
sme zapreti po odprtju okna z nastavitvami« napišemo »Okno naj ostane odprto v ozadju,
ko se nam odpre okno z nastavitvami«.
Na koncu še dodamo priloge, ki lahko pomagajo razvijalcu pri reprodukciji hrošča. Pri
dodajanju slik (ki so uporabne za prikaz statičnih problemov) označimo pomembne dele
ter jih dodamo v poročilo direktno – ne kopiramo jih v Word ali pa stiskamo v ZIP-arhiv.
Video naredimo in dodamo, če je napaka kompleksna in v njem ponazorimo, kako jo
reproduciramo. V videu moramo napako reproducirati po istih korakih, ki smo jih opisali
zgoraj v tekstu. Dodamo lahko tudi dnevniške in druge datoteke, če mislimo, da bodo
razvijalcu pomagale pri delu [4].
Za javljanje in odpravljanje hroščev lahko uporabljamo sisteme, s katerimi je testiranje in
odpravljanje hroščev bolj produktivno, kot je npr. Mantis bug tracker, Bugzilla, Trac ipd.
-
Testiranje programske opreme
32
8 PREDSTAVITEV UPORABLJENIH ORODIJ
8.1 Ogrodje QT
Pri izdelavi aplikacije za spremljanje pomnilnika bomo uporabili ogrodje QT, ki omogoča
izdelavo aplikacij za različne operacijske sisteme, v našem primeru na operacijskima
sistemoma Windows in Linux. QT ni programski jezik, ampak je ogrodje napisano v C++.
Uporablja preprocesor - t. i. »Meta-Object Compiler« oziroma MOC za razširitev
standardnega C++ jezika s funkcijami, kot so signali in reže (Slika 8.1).
Signali so sproženi ob določenih dogodkih, lahko pa jih prožimo tudi ročno (z ukazom
»emit«). Lahko jih ustvarimo sami, lahko pa uporabimo tudi že vnaprej definirane signale,
ki so prisotni za vsak element v QT grafičnem vmesniku (angl. widgets), kot so npr.
clicked, toggled, activated itn. Ko je signal sprožen, se reže povezane s signalom izvedejo
takoj. Koda, ki je takoj za »emit« ukazom, pa se izvede šele po tem, ko se izvajanje rež
konča. Če imamo več rež povezanih s signalom, se bodo le-te izvedle v takšnem vrstnem
redu, kot so bile povezane z njim.
Reže so klasične funkcije, ki se od drugih funkcij razlikujejo samo v tem, da so lahko
povezane s signali, s katerimi jih lahko prožimo [10].
Objekt1
Signal1
Signal2
Reža1
Objekt2
Signal1
Reža1
Reža2
Objekt3
Reža1
Objekt4
Signal1
Reža1
Reža2
Slika 8.1: QT-signali in reže
-
Testiranje programske opreme
33
Pred prevajanjem aplikacije s pomočjo ogrodja QT MOC razčleni izvorne datoteke in iz
njih generira standardne C++ vire. Nato lahko prevedemo aplikacijo s katerimkoli C++
prevajalnikom (GCC, Visual Studio …) [9].
Poleg QT-ogrodja dobimo tudi IDE QT-Creator (Slika 8.2), ki teče v Windows, Linux, MAC
OS X sistemih in ga lahko uporabimo za izdelavo in prevajanje aplikacij. Pri izdelavi naše
aplikacije ga bomo uporabili za izdelavo uporabniškega vmesnika ter prevajanje aplikacije
za operacijske sisteme Linux. Za kodiranje in razhroščevanje aplikacije pa bomo uporabili
vtičnik »Visual Studio Add-in«, ki nam bo omogočil, da bomo večino aplikacije (skoraj vse
razen uporabniškega vmesnika) izdelali v nam že poznanem IDE-ju Microsoft Visual
Studio.
Slika 8.2: QT-Creator
-
Testiranje programske opreme
34
8.2 Oracle VirtualBox
Oracle VirtualBox je virtualizacijska programska oprema, ki jo namestimo na obstoječ
operacijski sistem. S pomočjo te aplikacije lahko ustvarimo eno ali več navideznih naprav
- računalnikov, na katere lahko namestimo katerikoli podprt operacijski sistem, ne da bi s
tem spreminjali obstoječ sistem, na katerem aplikacija teče (Slika 8.3). VirtualBox lahko
namestimo na različne operacijske sisteme, kot so:
Windows,
Linux,
MAC OS X (samo na Applovih računalnikih),
Solaris,
Android.
Slika 8.3: Virtualbox ̶ navidezne naprave
V navideznih napravah pa lahko poganjamo različne izpeljanke in verzije teh operacijskih
sistemov npr.: Windows 10, Debian 8 (Slika 8.4), CentOS 6, MAC OS X 10.10. Zelo
pomembna funkcija, ki jo imajo virtualizacijski programi so t. i. »posnetki« (angl.
-
Testiranje programske opreme
35
snapshots), ki nam omogočajo, da shranimo stanje virtualne naprave. S tem prihranimo
veliko dela, saj nam po testiranju ni vedno treba ročno vzpostavljati sistema v želeno
stanje in lahko to naredimo z nekaj kliki. To nam zelo koristi pri vzpostavljanju in
shranjevanju čistega konstantnega testnega okolja in pri testiranju posodobitev naše
programske opreme.
V tem diplomskem delu bomo uporabili aplikacijo VirtualBox za poganjanje navideznih
računalnikov, na katere bomo namestili operacijske sisteme Windows 10 in Debian 8. Na
prvih dveh napravah bomo namestili 32 in 64-bitni različici operacijskega sistema Debian
8, na katerih bomo prevedli naš program za Linux operacijske sisteme. Potrebovali bomo
tudi dve napravi za testiranje naše aplikacije – kot smo v prejšnjih poglavjih omenili, je
priporočljivo testirati aplikacijo v svežem okolju in ne v okolju, kjer je bila napisana in
prevedena. Na prvo navidezno napravo bomo namestili operacijski sistem Windows 10,
na drugo pa operacijski sistem Debian 8.
Slika 8.4: Debian Linux v VirtualBox navidezni napravi
-
Testiranje programske opreme
36
9 RAZVOJ APLIKACIJE ZA TESTIRANJE PORABE POMNILNIKA
Na začetku razvoja aplikacije se odločimo o izgledu in funkcijah aplikacije. Odločili smo
se, da bomo v glavnem oknu aplikacije (Slika 9.1) imeli:
seznam procesov, ki trenutno tečejo na računalniku (seznam lahko uporabnik
osveži);
seznam s tipi pomnilnika, ki so na voljo za spremljanje, kjer uporabnik izbere,
katere tipe želi spremljati;
enote, v katerih se bo poraba pomnilnika prikazovala (kilo bajti, mega bajti in giga
bajti), ter preciznost (število decimalnih mest);
gumb, s katerim omogočimo/onemogočimo shranjevanje dobljenih vrednosti v
CSV-datoteko, pot do mape, v katero se bodo CSV-datoteke shranile, ter gumb, s
katerim to mapo izberemo;
vnosno polje, kjer bo uporabnik izbral, na kakšen interval naj se podatki o
pomnilniku osvežijo.
Slika 9.1: Glavno okno
-
Testiranje programske opreme
37
Na operacijskem sistemu Windows potrebuje aplikacija administratorske pravice (Da
aplikacija sama zahteva administratorske pravice, je to potrebno nastaviti pred
prevajanjem le-te). Privilegije naše aplikacije moramo povišati v t. i. »debug« privilegije,
da dobimo informacije o procesih, ki so bili zagnani z administratorskim ali katerim drugim
uporabniškim računom. To storimo tako, da odpremo proces, preverimo vrednost
želenega privilegija ter ga nastavimo.
Izvorna koda 9.1: Povišanje privilegijev aplikacije
HANDLE hToken;
OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES |
TOKEN_QUERY, &hToken);
LUID luid;
LookupPrivilegeValue(
NULL,
SE_DEBUG_NAME, // želeni privilegij
&luid ); // pridobi LUID-privilegija
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid; // dodelimo privilegij
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges( // nastavimo privilegij
hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES) NULL,
(PDWORD) NULL);
Pri razvoju aplikacije, ki bo tekla v dveh družinah operacijskih sistemov (Windows in
Linux) si bomo pomagali s preprocesorskima ukazoma #ifdef in #endif, s katerima
bomo definirali kateri deli kode naj se izvedejo na OS-Windows (Q_OS_WIN) ter kateri na
OS-Linux (Q_OS_LINUX).
-
Testiranje programske opreme
38
9.1 Izbira procesa in nastavitev
Ob zagonu aplikacije je potrebno napolniti seznam aplikacij. To naredimo tako, da
najprej pridobimo PID-e procesov, ki trenutno tečejo na sistemu. Na operacijskem sistemu
Windows PID-e procesov, ki tečejo, pridobimo s pomočjo sistemske funkcije
EnumProcesses, na operacijskih sistemih Linux pa te podatke pridobimo v /proc
datotečnem sistemu. To je navidezni datotečni sistem, ki ne vsebuje pravih datotek,
ampak samo sistemske informacije o procesih, pomnilniku, procesorju ter drugi strojni
opremi. Vsak proces, ki teče, ima svoj unikaten PID, ki je v /proc sistemu prikazan kot
direktorij. V našem programu to uporabimo tako, da pridobimo vse direktorije, katerih
imena so v celoti števila.
Izvorna koda 9.2: Pridobivanje trenutno aktivnih procesov
bool MainWindow::getRunningProcesses(){
#ifdef Q_OS_WIN
…
EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded);
nrOfProcesses = cbNeeded / sizeof(DWORD);
for (int i=0; i
-
Testiranje programske opreme
39
Ko smo pridobili PID-e procesov, pa pridobimo še njihova imena. Na operacijskih sistemih
Windows to storimo tako, da uporabimo funkcijo GetProcessImageFileName, s katero
pridobimo polno pot do izvršilne datoteke izbranega procesa. To funkcijo smo, namesto
funkcije »GetModuleBaseName«, uporabili zaradi tega, ker slednja velikokrat ne vrne
imena za določene sistemske funkcije – s funkcijo, ki smo jo uporabili dobimo več imen.
Na operacijskih sistemih Linux pa tako, da opremo datoteko status v direktoriju z
imenom PID-a (npr. za proces s PID-om 1234 odpremo datoteko /proc/1234/status),
preberemo prvi vrstico, ki vsebuje niz »Name:«, ter ta niz odstranimo.
Izvorna koda 9.3: Pridobivanje imena izbranega procesa
QString MainWindow::getProcessName(unsigned long processID) {
#ifdef Q_OS_WIN
…
GetProcessImageFileName(hProcess,szProcessName,sizeof(szProcessName));
…
#endif
#ifdef Q_OS_LINUX
…
if (inputFile.open(QIODevice::ReadOnly)){
processName = in.readLine();
processName = processName.remove(QRegularExpression("Name:"));
}
…
}
Po tem, ko smo dobili PID-e in pripadajoča imena procesov, pa samo napolnimo drevo s
pridobljenimi elementi.
Izvorna koda 9.4: Dodajanje pridobljenih podatkov v drevo
// Dodaj PID
processTreeItem->setData(0, Qt::DisplayRole, processes[0][i].toInt());
// Dodaj ime procesa
processTreeItem->setText(1, processes[1][i]);
// Dodaj element v drevo
ui->processesTreeWidget->addTopLevelItem(processTreeItem);
-
Testiranje programske opreme
40
Seznam tipov pomnilnika napolnimo glede na operacijski sistem, na katerem teče
aplikacija, saj so tipi pomnilnika, ki jih bomo spremljali na operacijskih sistemih Windows
in Linux različno poimenovani oziroma niso povsod na voljo. Na operacijskih sistemih
Windows (Slika 9.2) imamo na voljo: Working set, Pagefile, Page faults, Paged pool, in
non-paged pool.
Slika 9.2: Tipi pomnilnika – Windows
Na operacijskih sistemih Linux (Slika 9.3) pa: Resident set size, Virtual memory, Data
segments, Stack segments, Text segments, Shared library code size, Page table entries
size, Swapped virtual memory size.
Slika 9.3: Tipi pomnilnika – Linux
Izvorna koda 9.5: Dodajanje tipa pomniln