76
UNIVERZA V MARIBORU FAKULTETA ZA ELEKTROTEHNIKO, RAČUNALNIŠTVO IN INFORMATIKO Tadej Moharič TESTIRANJE PROGRAMSKE OPREME Diplomsko delo Maribor, oktober 2015

TESTIRANJE PROGRAMSKE OPREME · 2017. 11. 28. · iv Testiranje programske opreme Ključne besede: testiranje programske opreme, razvoj programske opreme, testiranje, poraba pomnilnika,

  • Upload
    others

  • View
    21

  • Download
    0

Embed Size (px)

Citation preview

  • 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