Top Banner
Bernard Atelšek TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV Diplomsko delo Maribor, september 2011
102

TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Aug 29, 2019

Download

Documents

doanthuy
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Bernard Atelšek

TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV

Diplomsko delo

Maribor, september 2011

Page 2: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala
Page 3: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

I

Diplomsko delo univerzitetnega študijskega programa

TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV

Študent: Bernard Atelšek

Študijski program: UN ŠP – računalništvo in informatika

Smer: Informatika

Mentor: red. prof. dr. Marjan Heričko

Lektorica: Irena Žunko, prof.

Maribor, september 2011

Page 4: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

II

Page 5: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

III

ZAHVALA

Zahvaljujem se mentorju – red. prof. dr.

Marjanu Heričku za pomoč in vodenje pri

pisanju diplomskega dela.

Posebna zahvala velja staršem, ki so mi

omogočili študij. Hvala tudi lektorici.

Page 6: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

IV

TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV

Ključne besede: informacijski sistemi, agilni razvoj, testno voden razvoj,

avtomatizirano testiranje, testiranje enot

UDK: 659.2:004(043.2)

Povzetek

Diplomsko delo predstavlja testno voden pristop k razvoju programskih rešitev (TDD).

Podali smo definicije in koncepte ter navedli razloge za nastanek te metode. Opisali

smo tudi agilne metode razvoja programske opreme ter predstavili preoblikovanje kode,

saj gre za pomemben del TDD. V nadaljevanju smo se posvetili testiranju – predvsem

avtomatiziranemu. Navedli smo izbrana ogrodja za testiranje enot (xUnit) in definirali

še druge vrste testiranj. Diplomsko delo pa podaja praktični primer razvoja programske

opreme po metodi TDD. Med samim razvojem smo merili posamezne aktivnosti in jih na

koncu tudi primerjali s podobnim eksperimentom.

Page 7: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

V

TEST-DRIVEN SOFTWARE DEVELOPMENT

Key words: information systems, agile development, test driven development,

test automation, unit testing

UDK: 659.2:004(043.2)

Abstract

This thesis presents test-driven development (TDD). We describe concepts, definitions

and try to explain the reasons behind the formation of this development method. We

also describe agile software development methods with refactoring as one of the main

ingredients of TDD. Furthermore we focused mainly on testing, especially test

automation. We mentioned a few frameworks for unit testing (xUnit) and other testing

techniques. The accumulated theoretical knowledge was used to develop a prototype

project with TDD. During the process of development we measured separate activities

and compared the time distribution with a similar experiment.

Page 8: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

VI

VSEBINA

1 UVOD ...................................................................................................................... 1

2 TESTNO VODEN RAZVOJ ................................................................................. 3

2.1 KRATKA ZGODOVINA RAZVOJA PROGRAMSKIH REŠITEV .................................... 3

2.2 AGILNI MANIFEST .............................................................................................. 4

2.3 PRINCIPI AGILNIH METOD .................................................................................. 4

2.4 EKSTREMNO PROGRAMIRANJE (XP) .................................................................. 5

2.4.1 Razširjeno ekstremno programiranje (XP2) ................................................ 7

2.5 DOMENSKO NAČRTOVANJE ................................................................................ 7

2.6 TESTNO VODEN RAZVOJ ..................................................................................... 9

2.6.1 Mejniki TDD ................................................................................................. 9

2.6.2 Definicija in umestitev TDD ....................................................................... 10

2.6.3 Razvojni cikel testno vodenega razvoja ...................................................... 13

2.6.3.1 Napiši test enote, ki pade .................................................................... 15

2.6.3.2 Poskrbi, da bo test uspešen ................................................................. 16

2.6.3.3 Preoblikuj ........................................................................................... 16

2.6.4 Razvoj voden s prevzemnimi testi ............................................................... 18

2.6.5 Vedenjsko voden razvoj .............................................................................. 20

2.6.6 Eksperimentalno voden razvoj.................................................................... 22

2.6.7 TDD in zastarela koda ................................................................................ 23

2.6.7.1 Analiziranje sprememb ....................................................................... 24

2.6.7.2 Priprave na spremembe ...................................................................... 24

2.6.7.3 Testno voden vnos sprememb ............................................................ 25

2.6.8 Čista koda ................................................................................................... 25

2.6.9 Prednosti in slabosti TDD .......................................................................... 26

2.6.10 Testi kot dokumentacija .......................................................................... 27

2.6.11 Zunanja in notranja kvaliteta ................................................................. 28

2.6.12 Kaj testirati? ........................................................................................... 29

2.6.13 Principi TDD .......................................................................................... 30

2.6.14 TDD-anti-vzorci ..................................................................................... 31

3 AVTOMATIZIRANO TESTIRANJE ................................................................ 33

Page 9: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

VII

3.1 CILJI AVTOMATIZIRANEGA TESTIRANJA ........................................................... 34

3.1.1 Testi naj bi izboljšali kvaliteto .................................................................... 34

3.1.2 Testiranje naj bi pomagalo razumeti sistem, ki ga razvijamo .................... 35

3.1.3 Testi naj bi zmanjšali tveganje ................................................................... 35

3.1.4 Testi naj bi bili enostavni za izvajanje ....................................................... 36

3.1.5 Testi naj bi bili enostavni za pisanje in vzdrževanje .................................. 37

3.1.6 Testi naj bi zahtevali minimalno vzdrževanje ............................................. 37

3.2 MANIFEST AVTOMATIZIRANEGA TESTIRANJA .................................................. 38

3.3 PROBLEMI PRI AVTOMATIZACIJI ....................................................................... 38

3.4 KATERE TESTE AVTOMATIZIRATI? ................................................................... 41

3.5 TESTIRANJE ENOT ............................................................................................ 43

3.5.1 Testiranje in izolacija ................................................................................. 44

3.5.2 Ogrodja za testiranje .................................................................................. 45

3.5.3 Poimenovanje testov ................................................................................... 46

3.5.4 Struktura testa enote ................................................................................... 47

3.5.5 Pokritost kode s testi ................................................................................... 47

3.6 INTEGRACIJSKO TESTIRANJE ............................................................................ 48

3.7 SISTEMSKO TESTIRANJE ................................................................................... 49

3.8 PREVZEMNO TESTIRANJE ................................................................................. 50

3.9 VEDENJSKO TESTIRANJE .................................................................................. 52

3.10 A/B TESTIRANJE .............................................................................................. 53

4 SODOBNI KONCEPTI RAZVOJA PROGRAMSKIH REŠITEV ................ 55

4.1 VZOREC MVVM ............................................................................................. 55

4.2 OBRAT KONTROLE ........................................................................................... 56

4.3 VRIVANJE ODVISNOSTI .................................................................................... 56

4.4 STALNA INTEGRACIJA ...................................................................................... 56

4.5 NAČRTOVALSKI VZORCI .................................................................................. 57

4.6 PRINCIPI SOLID .............................................................................................. 57

4.7 PRAKTIČNI NASVETI ZA PROGRAMIRANJE IN TESTIRANJE ................................. 58

5 PRAKTIČNI PRIMER RAZVOJA PO METODOLOGIJI TDD .................. 59

5.1 PREDSTAVITEV IN IDEJA .................................................................................. 59

Page 10: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

VIII

5.2 ITERACIJA NIČ ................................................................................................ 60

5.3 REŠITEV ........................................................................................................... 63

6 ANALIZA .............................................................................................................. 71

6.1 ZAKLJUČEK ..................................................................................................... 77

7 SKLEP ................................................................................................................... 79

8 VIRI ....................................................................................................................... 80

9 PRILOGE .............................................................................................................. 84

9.1 SEZNAM SLIK ................................................................................................... 84

9.2 SEZNAM TABEL ................................................................................................ 86

9.3 NASLOV ŠTUDENTA ......................................................................................... 86

9.4 KRATEK ŽIVLJENJEPIS...................................................................................... 87

Page 11: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

IX

UPORABLJENE KRATICE

(D)VCS (Porazdeljen) Sistem za upravljanje konfiguracije (angl. (Distributed) Version

Control System)

AAA Sintaksa Pripravi-Izvedi-Preveri (angl. Arrange-Act- Assert)

API Programski vmesnik (angl. Application Programming Interface)

ATDD Razvoj voden s prevzemnimi testi (angl. Acceptance Test Driven Development)

BDD Vedenjsko voden razvoj (angl. Behavior Driven Development)

CI Stalna integracija (angl. Continuous integration)

DDD Domensko načrtovanje (angl. Domain-driven design)

DI Vrivanje odvisnosti (angl. Dependency Injection)

DIP Princip obrata odvisnosti (angl. Dependency Inversion Principle)

DSL Domensko specifičen jezik (angl. Domain-specific language)

EDD Eksperimentno voden razvoj (angl. Experiment Driven Development)

GUI Grafični vmesnik (angl. Graphical User Interface)

IDE Integrirano razvojno okolje (angl. Integrated Development Environment)

IOC Obrat kontrole (angl. Inversion of Control)

ISP Princip vmesniške ločitve (angl Interface Segregation Principle)

LSP Princip Liskove zamenjave (angl. Liskov Substitution Principle)

MVC Vzorec Model-Pogled-Upravljalec (angl. Model-View-Controller)

MVVM Vzorec Model-Pogled-Vmesnik (angl. Model-View-ViewModel)

OCP Princip odprtosti in zaprtosti (angl. Open Closed Principle)

SCM Sistem za upravljanje konfiguracije (angl. Software Configuration Management)

SOLID Kombinacija akronimov SRP, OCP, LSP, ISP, DIP

SRP Princip ene odgovornosti (angl. Single Responsibility Principle)

SUT Sistem, ki se testira (angl. System Under Test)

TDD Testno voden razvoj (angl. Test Driven Development)

TFP Programiranje po testu (angl. Test-First Programming)

TLD Testiranje po implementaciji (angl. Test-Last Development - TLD)

V&V Verifikacija in validacija (angl. Verification and Validation)

XP Ekstremno programiranje (angl. Extreme Programming)

XP2 Razširjeno ekstremno programiranje

XUNIT Ogrodje za testiranje enot (npr. JUnit, NUnit)

Page 12: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala
Page 13: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 1

1 UVOD

Programska rešitev je rezultat nekega razvojnega procesa. Vsak projekt pa mora biti

ustrezno voden, saj se v nasprotnem primeru bodisi ne konča v roku ali pa preseže

načrtovane stroške. Tako kot celoten projekt mora biti planiran in ustrezno strukturiran

tudi sam razvojni proces. Gre za zaporedje aktivnosti, ki so rezultat preteklih izkušenj in

predstavljajo dobre prakse [17].

Bolj kot sama implementacija predstavlja problem odnos med razvijalci in naročniki.

Zbiranje in usklajevanje zahtev je še posebej zahtevno, saj obe strani razpolagata z

različnimi predznanji. Edina konstantna stvar v računalništvu pa so spremembe. Vse to pa

morajo razvijalci pričakovati in tudi biti sposobni se odzivati na spremembe. Tudi pisanje

dokumentacije zahteva ogromno režije, sploh pri spremembah. Dejstvo pa je, da nihče ne

bere te dokumentacije – vsak razvijalec raje preleti izvorno kodo ali pa dokumentacijo

samo na hitro prelista. Poleg tega pa je nihče ne piše rad in je samo dodatna obremenitev

za že tako zaposlene razvijalce. V današnjih časih pa je, roko na srce, glavni cilj hitrost.

Zahtevajo se boljše programske rešitve v krajšem času [16].

Zaradi teh izzivov so nastale t. i. agilne metode. Gre za čisto nasprotje togih procesov, ki

so se uporabljali v preteklosti. Njihov cilj je boljše odzivanje na spremembe, samo

najnujnejše pisanje dokumentacije ter testiranje. Vse to pa se izraža v hitrejšem razvoju,

boljši programski kodi in v znosnejših razmerah na delovnem mestu.

Najbolj znana agilna metoda je ekstremno programiranje (XP) [15]. Pokriva planiranje,

testiranje, vzdrževanje in namestitev programskih rešitev. Večji projekt razdeli na več

manjših, za vsako iteracijo pa se sproti določijo funkcionalnosti, ki bodo implementirane

[15].

Programiranje po testu (angl. Test First Programming – TFP) je koncept, kjer že pred

implementacijo napišemo test. To nam zagotavlja kvalitetnejšo implementacijo, saj imamo

na voljo več informacij in časa za načrtovanje. Količina testov se poveča z vsako dodano

funkcionalnostjo, vsi pa morajo uspeti.

Page 14: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 2

Če to kombiniramo s preoblikovanjem kode, dobimo testno voden razvoj (angl. Test

Driven Development – TDD). Pri tej metodologiji razvoj narekujejo testi, ki so

avtomatizirani. Večinoma se testiranje kode izvaja na t. i. xUnit ogrodjih za testiranje.

Rezultat takšnega razvoja je običajno minimalna programska koda, ki zadosti vsem

zahtevam.

TDD sam po sebi sicer ničesar ne zagotavlja, promovira pa sodoben način razvoja

programskih rešitev [15].

Osnovni cilji diplomske naloge so: prvič – umestitev, definiranje in predstavitev testno

usmerjenega razvoja programske opreme, drugič – razložiti avtomatizirano testiranje ter

tretjič – razviti pilotski projekt s pomočjo vsega naštetega. Namen je podrobno definirati

TDD (koncept, zgodovino, prednosti in slabosti), testiranje ob razvoju (ogrodja, principi)

ter takšen razvojni cikel preslikati v prakso in tako razviti konkreten projekt. Diplomska

naloga bo promovirala agilnost, preoblikovanje in testiranje kode ter tako prispevala k

razvoju konkurenčnejših programskih rešitev.

Prvo poglavje diplomskega dela predstavlja uvod, v katerem so opisani cilji in splošno

področje raziskav. V drugem poglavju preko agilnih metod hitro pridemo do testno

usmerjenega razvoja – ga definiramo, umestimo in predstavimo. V nadaljevanju

predstavimo še preoblikovanje kode – definicije in dobre prakse. V naslednjem poglavju

obravnavamo testiranje. Poudarek je na avtomatiziranem testiranju in ogrodjih za

testiranje. V predzadnjem poglavju pa obravnavamo praktični primer – razvoj pilotskega

projekta po teoriji, predstavljeni v tej diplomi – od ideje, načrtovanja, vmesnikov do

implementacije. V zaključku povzamemo izkušnje in ugotovitve, zaključimo pa s

seznamom slik, tabel in uporabljenih virov.

Page 15: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 3

2 TESTNO VODEN RAZVOJ

V tem poglavju bomo postopoma poskušali definirati testno usmerjen razvoj programske

opreme (TDD). Opisali bomo nastanek, definirali nekatere povezane pojme in opisali

razvojni cikel. Razložili bomo prednosti in slabosti ter primerjali z razvojnimi procesi, ki

so se uporabljali pred tem.

2.1 Kratka zgodovina razvoja programskih rešitev

Na začetku so bili vsi projekti brez ustreznega vodenja. Razvoj je običajno temeljil na

enem razvijalcu, ki je dobro poznal uporabljeno tehnologijo in sam problem. Jasno je, da

takšni projekti, ki niso bili ustrezno načrtovani, običajno niso bili ustrezni za stranko.

Logična posledica je bila, da se je začel razvoj programske opreme formalizirati [18].

Proces razvoja se je razdelil na posamezne korake in pripadajoče postopke. Različne

metodologije so se začele pojavljati med leti 1970 in 1980. Kmalu pa so postale tudi zelo

obsežne. Nekatere programske hiše so razvile svoje lastne metodologije in jih dolgo tudi

uspešno prodajale. Vse je bilo do potankosti razdelano in primerno za večje ekipe.

Potrebno je bilo voditi veliko dokumentacije, kar je zahtevalo ogromno režije. V razvojnih

ekipah pa je vsaka oseba nepogrešljiva, niti nihče ne piše in vzdržuje dokumentacije prav

rad. Uvesti je bilo potrebno nekaj »lažjega«, kar bo primerno za manjše skupine in bo bolj

prilagodljivo. Nastale so agilne metode [19].

Page 16: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 4

2.2 Agilni manifest

Vse agilne metode temeljijo na t. i. agilnem manifestu. Njegova vsebina narekuje smernice

in podaja bistvo agilnih metod [1].

Posamezniki in sodelovanje med njimi je pomembnejše od procesa in orodij.

Delujoči sistem je pomembnejši kot dokumentacija.

Sodelovanje naročnika je pomembnejše od pogajanj glede pogodbe.

Odzivnost na spremembe namesto strogega upoštevanja planov.

Pred tem so bile v ospredju vrednote, ki so tukaj zapisane na desni strani alinej. Od sedaj

najprej pa je poudarek na vrednotah zapisanih na levi strani, kar pa ne pomeni, da desnih ni

več.

2.3 Principi agilnih metod

Agilnost lahko na daljše opišemo s pomočjo naslednjih principov [1].

Glavni cilj je zadovoljstvo stranke. To se doseže z zgodnjimi in pogostimi izdajami

programske opreme.

Spremembe so dobrodošle, celo pozno v razvojnem ciklu. Agilni proces izkorišča

spremembe za doseganje konkurenčne prednosti naročnika.

Pogoste izdaje z delujočimi funkcionalnostmi, vsakih nekaj tednov do vsakih nekaj

mesecev. Boljše je, če so izdaje bolj pogoste.

Naročniki in razvijalci morajo biti ves čas razvoja projekta v stiku.

V središču projekta naj bodo motivirani posamezniki. Nuditi jim je potrebno okolje

in podporo, ki jo potrebujejo, ter jim zaupati, da bodo delo opravili kvalitetno.

Najučinkovitejši način prenosa informacij v razvojni ekipi je neposreden pogovor.

Delujoča programska rešitev je največji pokazatelj napredka projekta.

Agilni proces zagovarja stalen razvoj. Naročniki, razvijalci in uporabniki morajo

vzdrževati stalen tempo dela.

Stalno je treba posvečati pozornost tehnični odličnosti in dobremu načrtovanju, saj

povečujeta agilnost.

Preprostost – sposobnost izločanja nepotrebnega dela – je poglavitna.

Page 17: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 5

Najboljše arhitekture, zahteve in načrti izhajajo iz dobro organiziranih razvojnih

ekip.

Vsake toliko časa naj razvojna ekipa pregleda možnosti, kako bi bila še bolj

učinkovita. Glede na ugotovitve pa potem izpili in prilagodi način dela.

2.4 Ekstremno programiranje (XP)

Gre za eno bolj popularnih agilnih metodologij, ki se je že dokazala za zelo uspešno v

podjetjih po vsem svetu. Glavni razlog je to, da poudarja zadovoljstvo stranke. Namesto

enkratne predaje programske opreme v daljni prihodnosti, ekstremno programiranje stalno

dostavlja nove funkcionalnosti, ki so usklajene z zahtevami stranke. Kot agilna metoda se

je sposobna odzivati na spremembe tudi pozno v razvojnem ciklu [2].

Zagovarja skupinsko delo, kjer so razvijalci, stranke in vodstvo enakovredni člani ekipe.

Vsak pa je odgovoren za svoje področje. Zagotavlja okolje, v katerem so lahko vsi v ekipi

maksimalno produktivni. XP vpliva na razvoj programskih rešitev preko petih ključnih

vrednot [16]:

komunikacija,

preprostost,

odzivnost,

pogum in

spoštovanje.

Pomembno je, da so razvojne ekipe majhne (do 12 ljudi), saj se le tako izognemo dolgim

sestankom in ohranimo komuniciranje enostavno in jasno. Za XP je značilno tudi sprotno

določanje funkcionalnosti, ki se bodo implementirale kot naslednje. Določi jih stranka

glede na lastne potrebe.

Razvojni cikel je razdeljen na več kratkih iteracij, v katerih se implementirajo nove

funkcionalnosti. Na takšen način pa hitro dobivamo jasno sliko o napredku samega

projekta in tako lažje ukrepamo. Bistvo pa je seveda delujoča programska oprema, ki je v

skladu z željami stranke. To se pa zagotavlja s testiranjem enot in prevzemnimi testi. Vse

pa naj bo avtomatizirano. Seveda pa XP ni zacementiran tako kot je predlagan v literaturi.

Nasprotno – celo spodbuja se prilagajanje. Na takšen način lahko izberemo in uporabimo

Page 18: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 6

dobre prakse iz vseh razvojnih metodologij in jih kombiniramo z XP. S tem dobimo

agilnost v pravem pomenu besede – na vseh točkah razvoja.

Razvojni proces je definiran s štirimi spremenljivkami, od katerih tri določi stranka, eno pa

razvijalec [16]. To so:

stroški,

čas,

kakovost,

obseg.

Pomembno je omeniti še priporočene prakse – in relacije med njimi (Slika 1).

Slika 1: Prakse ekstremnega programiranja [20]

Page 19: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 7

2.4.1 Razširjeno ekstremno programiranje (XP2)

Tudi ekstremno programiranje se je skozi čas razvijalo in se prilagajalo. Leta 2004 je bilo

posodobljeno in dopolnjeno z nekaterimi dodatnimi praksami. To pa še ni vse, saj se sedaj

prakse delijo na primarne in napredne (Slika 2). Uvedba slednjih je zahtevna in nevarna, če

prej nismo osvojili povezanih primarnih praks. Seveda pa je najboljše, če preizkusimo in

potem po potrebi korigiramo. Število primarnih praks se je povečalo na 13, naprednih pa je

11. To nam pove, da je metodologija ustrezna in široko uporabljana [15].

Slika 2: Prakse pri XP2 [15]

2.5 Domensko načrtovanje

Programske rešitve se najpogosteje uporabljajo pri avtomatizaciji procesov, ki obstajajo v

realnem svetu. Prav tako lahko rešujejo konkretne poslovne probleme. Ti procesi in

problemi predstavljajo domeno teh programskih rešitev. Čeprav so aplikacije sestavljene iz

programske kode, je potrebno nanje gledati širše – ne samo kot na skupek objektov in

metod [45].

Za preproste probleme je to lahko ustrezna rešitev, za kompleksnejše pa je to nemogoče.

Za dobre programske rešitve je potrebno dobro poznavanje ozadja, ki ga aplikacija rešuje.

Potrebno je podrobno poznavanje domene problema, ki se rešuje.Domene pa seveda ne

poznajo računalniški arhitekti, analitiki, še manj pa razvijalci. Najboljše jo poznajo tisti, ki

Page 20: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 8

so zaposleni v panogi, ki jo domena pokriva. Najboljše pa je takšne ljudi poiskati kar v

okolici naročnika. Tako dobimo dostop do virov, ki posedujejo znanje, podrobnosti, trike

in poznajo potencialne prepreke našega problema. Razviti je potrebno izdelek, ki se bo

brez težav vključil v okolje domene [45].

Najboljše je, da programska rešitev odraža domeno. Vsebuje naj glavne koncepte,

elemente domene in vse povezave med njimi. Rešitev naj modelira domeno. Če temu ni

tako, bo vzdrževanje zelo zahtevno.

Poznavanje domene pa ni mogoče kar tako preslikati v programsko kodo. V ta namen je

potrebno narediti abstrakcijo domene. To je model znanja, ki ga posedujejo strokovnjaki

domene. Predstavlja načrt, ki je na začetku precej pomankljiv, a ga sčasoma dopolnjujemo,

ko zadeve postajajo jasnejše tudi razvojni ekipi. To lahko naredimo s pomočjo diagramov,

skrbno napisane programske kode ali pa kar z vezanim besedilom.

Model predstavlja naše razumevanje ciljne domene. Nemogoče je kar naenkrat spoznati

vse. Informacije si je potrebno organizirati in sistematizirati. Celoto pa razdeliti na manjše

dele in jih povezati v logične module. Manjše enote lažje obvladamo, nekaj pa jih je

potrebno tudi izpustiti. Domena je namreč prevelika, da bi jo lahko celo vključili v model.

Pa tudi potrebe ni, da vključujemo enote, ki niso neposredno povezane z našim

problemom. Kaj vključimo in kaj ne pa je del načrtovanja oz. razvojnega procesa.

Dobljeni model je potrebno izraziti in deliti s člani razvojne ekipe. Znanje in informacije je

potrebno deliti. To lahko naredimo s pomočjo grafike ali besedila. Priporočljivo je

definirati tudi jezik domene, ki ga uporabljajo in razumejo vsi vpleteni [45].

Ko je model zadovoljiv, se prične delo na načrtovanju programske kode. Dobra koda je

pomembna sestavina končnega izdelka. Priporočljiva je uporaba načrtovalskih vzorcev.

Dobre tehnike kodiranja naredijo kodno osnovo čisto in lažjo za vzdrževanje.

Razvoj takšnih rešitev poteka s pomočjo tradicionalnih ali agilnih metodologij. Domensko

vodeno načrtovanje (angl. Domain-driven design – DDD) kombinira načrtovalske in

razvojne prakse, ki vodijo do boljših programskih rešitev.

Page 21: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 9

2.6 Testno voden razvoj

Testno voden razvoj (angl. Test-driven development – TDD) je drugo ime za

programiranje po testu (angl. Test-First Programming – TFP). Še vedno pa marsikoga

zavede, da gre za testiranje. V osnovi gre za razvojno metodologijo, ki je zelo enostavna, a

hkrati tako radikalno drugačna. Ideja je, da se testi napišejo že pred dejansko

implementacijo. Ta praksa se večini zdi skregana z logiko, ampak po krajšem premisleku

vidimo, da temu ni tako [3], [4].

2.6.1 Mejniki TDD

Sam po sebi pa TDD ni nič neverjetnega ali revolucionarnega. Je samo kombinacija metod,

ki so znane že dolgo časa, a so bile mogoče različno uporabljane. Paralele lahko iščemo že

na začetku našega obstoja.

Tabela 1: Mejniki TDD [5], [6]

Letnica Pomembni dogodki

Pred našim

štetjem

Ožgan kos mesa kot prvi uspešen testni primerek. Jamski človek opisuje drugemu, kako

mu je uspelo zanetiti ogenj in kakšen je rezultat.

1815–1852 Ada Lovelace kot prva nevede pokaže na koncept TDD s preverjanjem rezultatov, pa

čeprav še ni imela na voljo računalnika.

1959–1963 Programerji Merkurjevega vesoljskega programa so uporabljali neko vrsto TDD za

programiranje luknjanih kartic.

1989 Gerry Weinberg in Gary Goldberg sta programirala po testu luknjane kartice.

Ward Cunningham je napisal prvo ogrodje za testiranje – Fit-like.

1994 Kent Beck napiše ogrodje za testiranje – Sunit.

1995–1999 Kent Beck demonstrira TDD Wardu Cunninghamu.

Koncept ekstremnega programiranja (XP) pride v javnost iz projekta C3.

Izid knjige o preoblikovanju kode – Refactoring: Improving the Design of

Existing Code.

Izid knjige o XP – Extreme Programming Explained.

Pojavi se prvi vodič za TDD (Xp Immersion One konferenca).

2000

Pojavi se spletna stran JUnit.org.

Začne se razvoj ogrodij NUnit in JUnit.

Prvi članek o oponašanju objektov.

2001

Nat Pryce napiše knjižnico za nadomeščanje objektov v Rubyu in jo predela še

za Javo. Nastane jMock.

Chris Stevenson predstavi poimenovanje za teste v obliki stavkov.

2002

TFP se preimenuje v TDD.

Izid prve knjige o TDD – Unit Tests mit Java – v nemščini.

Kent Beck napiše knjigo Test Driven Development By Example.

Razvojno okolje Eclipse dobi podporo za JUnit.

Page 22: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 10

2003

Izid knjige Unit Testing In Java: How Tests Drive the Code.

Izid knjige Test Driven Development a Practical Guide.

2004 Izid knjige Extreme Programming Adventures.

Podpora za testiranje v Ruby On Rails.

Izid knjig Refactoring To Patterns, Junit Recipes, Working Effectively With

Legacy Code.

Martin Fowler objavi članek Mocks aren't stubs.

2005 Izid knjige Agile Java.

JUnit dobi podporo za trditve (angl. Asserts).

Microsoft po svoje definira TDD.

2007 Izid knjige Test Driven Practical TDD and Acceptance TDD for Java

Developers.

Predstavljen koncept BDD (angl. Behavior-driven development).

2008 Koncept razvoja vodenega s prevzemnimi testi (ATDD).

Prvi patent na temo TDD (Parameterized test driven development).

2009 Izid knjig Acceptance Test Engineering Guide, Agile Testing – A Practical

Guide for Testers and Agile Teams.

Microsoft izda ogrodje ASP.NET MVC.

Izid knjige ASP.NET MVC 1.0 Test Driven Development: Problem – Design –

Solution.

Izid knjige Clean Code: A Handbook of Agile Software Craftsmanship.

2010 Izid knjige Test-Driven Development: An Empirical Evaluation of Agile

Practice.

Izid knjige Domain-Specific Model-Driven Testing.

Izid knjige Growing Object-Oriented Software, Guided by Tests.

Microsoft izda ogrodji ASP.NET MVC 2 in MVC 3 BETA.

2.6.2 Definicija in umestitev TDD

Skoraj vsak programerski projekt predstavlja nekaj, kar še nihče izmed razvijalcev v ekipi

ni delal prej (na lokalni ali svetovni ravni). Običajno gre za kombinacijo vpletenih ljudi,

uporabljene tehnologije in problemske domene aplikacije. Ne glede na vložen trud vsi

projekti (razen rutinskih) vsebujejo elemente presenečenja. To se zelo pogosto zgodi ravno

pri projektih, ki bi morali prinesti največji dobiček [4].

Običajno se razvijalci poleg same problematike implementacije srečujejo tudi s problemi

uporabe tehnologije. Tudi če odlično poznajo tehnologijo, jih aplikacija, ki se razvija,

postavlja pred nove izzive, dileme in jih tako potiska na neznan teren. S podobnimi

problemi pa se srečujejo tudi stranke in uporabniki. Z razvojem projekta se morajo tudi

Page 23: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 11

sami učiti in podrobno spremljati dogajanje. Potrebne so analize in formalizacije procesov,

ki jim do sedaj niso posvečali prevelike pozornosti.

Vsak, ki je vpleten pri programerskem projektu, se mora učiti skladno z napredkom

projekta. Vsi morajo delati skupaj, da lahko razumejo problematiko in rešujejo tekoče

probleme. Vsakemu je jasno, da bo prišlo do sprememb, nihče pa ne ve točno, kakšne bodo

te spremembe. Potrebni so mehanizmi, ki bodo pomagali spopadati se s spremembami –

pričakovati nepričakovano. Razvoj aplikacij je učni proces [4].

Najboljši pristop je, če ekipa za učenje in spoznavanje sistema uporablja povratne

informacije. Vse tako pridobljene izkušnje pa potem uporabi pri nadaljnjem razvoju. Ekipe

naj razvijajo aplikacije v ponavljajočih ciklih (Slika 3). V vsakem ciklu dodajo nekaj novih

funkcionalnosti, potem pa iz povratnih informacij dobijo sliko o napredku. Delo se razdeli

na časovne enote, v katerih se izvaja analiza, načrtovanje, implementacija in namestitev

novih funkcionalnosti.

Namestitev na novo dodanih funkcionalnosti ob koncu vsakega cikla je ključnega pomena.

Takrat imajo razvijalci priložnost, da vidijo, kako se sistem obnaša v realnih razmerah. To

je priložnost za ocenjevanje napredka, odpravljanje napak in za prilagajanje poteka razvoja

glede na pridobljene informacije. Brez namestitve povratna informacija ni popolna.

Razvoj v ciklih na vseh stopnjah razvoja omogoča lažje odkrivanje napak. Zunanji (večji)

razvojni cikli razkrivajo pomanjkljivosti, ki so se zgodile v notranjih (manjših) ciklih.

Povratne informacije teh ciklov pokrivajo različne dele razvijajočega se sistema in

razvojnega procesa. Notranji cikli so bolj osredotočeni na tehnične lastnosti sistema.

Zunanji pa bolj na razvojno ekipo in samo organiziranost [4].

Slika 3: Razvoj v ciklih in odvisnosti med njimi [9]

Page 24: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 12

Načinu razvoja z gnezdenimi cikli pravimo inkrementalen in iterativen (Slika 4).

1. Inkrementalnost – sprotno dodajanje novih funkcionalnosti. Tako je vsaka

funkcionalnost vedno implementirana do konca, celoten sistem pa je vedno

pripravljen za namestitev.

2. Iterativnost – postopna implementacija funkcionalnosti glede na sprotne odzive

dokler stranka ni zadovoljna.

Slika 4: Inkrementalni in iterativni razvoj [21]

Prej ko lahko dobimo kakršnokoli povratno informacijo o sistemu, ki se gradi, boljše je.

Veliko razvojnih ekip izdaja nove različice tedensko ali celo dnevno. To jim zelo poveča

frekvenco kvalitetnih povratnih informacij od dejanskih uporabnikov.

Za zanesljiv in dinamičen razvoj programskih rešitev se moramo držati dveh tehničnih

pravil. Stalno testiranje omogoča dodajanje novih funkcionalnosti, brez da bi pokvarili že

dodane. Testiranje naj bo avtomatsko, saj je ročno prepočasno in nepraktično. Na takšen

način zmanjšamo stroške razvoja, namestitve in spreminjanja sistema.

Page 25: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 13

Kot drugo pa naj bo izvorna koda kar se da enostavna in čista, da jo je lažje razumeti in

vzdrževati. Razvijalci običajno porabijo dosti več časa za branje izvorne kode kot pa za

dejansko implementacijo. V to je treba vlagati veliko truda, zato stalno preoblikujemo

izvorno kodo. Tako izboljšamo in poenostavimo arhitekturo, odstranimo podvajanje kode

in jasneje pokažemo, kaj ta koda počne. Testi pa skrbijo, da s preoblikovanjem ne

pokvarimo delujočih funkcionalnosti.

TDD pa stvari obrne na glavo. Najprej napišemo teste, potem pa šele izvorno kodo.

Testiranje tukaj nima več običajne vloge, saj postane testiranje del načrtovanja. S pomočjo

testov razvijalci definirajo, kaj naj bi izvorna koda delala. Na takšen način ločimo logično

od fizičnega načrtovanja. TDD daje stalne povratne informacije o kvaliteti naše

arhitekture, to pa običajno pomeni čistejšo izvorno kodo in bolj modularno arhitekturo.

Z avtomatiziranimi testi pa si tudi zagotovimo varovalo, ki nam daje samozavest za

spremembe. Vsakdo se strinja, da je zelo priporočljivo imeti napisane teste enot. Bolj kot

je programska koda pokrita s testi enot, bolj je prilagodljiva. Kajti velik nabor testov

zagotavlja nizko stopnjo napak v programski kodi. To pa še ni vse. Omogoča tudi lažje

dodajanje novih funkcionalnosti ter vnašanje sprememb v kodo. Običajna pokritost kode s

testi naj bi bila okoli 80 % [2].

Največ se TFP uporablja v agilnih programerskih ekipah, najdemo pa ga tudi drugod. Je

tudi osnovna praksa pri ekstremnem programiranju (XP), priporoča pa se uporaba tudi v

Crystal (družina agilnih metodologij, ki se osredotočajo na projektno varnost) in Scrum

(iterativna in inkrementalna metodologija za vodenje agilnih projektov) projektih.

2.6.3 Razvojni cikel testno vodenega razvoja

Razvojni cikel je v osnovi zelo enostaven (Slika 5, Slika 6) [4]:

1. Napišite test.

2. Poskrbite, da bo test uspešen.

3. Preoblikujte kodo.

Zlato pravilo TDD pa je, da ne dodajamo novih funkcionalnosti, ne da bi poprej napisali

test, ki seveda pade [7]. Podrobneje si bomo te točke pogledali v nadaljevanju.

Page 26: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 14

Testno-razvojni cikel v praksi zgleda nekako takole [2]:

1. Napišite test.

2. Prevedite ga. Test se ne prevede, ker še niste implementirali kode, ki jo test kliče.

3. Implementirajte samo toliko, da se bo test lahko prevedel.

4. Poženite test in preverite, da test pade.

5. Implementirajte samo toliko, da bo test uspešen.

6. Poženite test in preverite, če je uspešen.

7. Preoblikujte kodo za večjo jasnost.

8. Ponavljajte vse te korake.

Programer začne s pisanjem testa, ki se prvič niti ne prevede. To je razumljivo, saj klicana

programska koda niti ne obstaja. Glede na napisan test potem postavi ogrodje – razrede in

metode, ki jih test kliče. V drugem poskusu bi se naj test prevedel, ampak mora pasti.

Tukaj šele prvič pridemo do implementacije tistega dela funkcionalnosti, za katerega smo

prej napisali test. Implementira se samo toliko, da je test uspešen. Programska koda naj bo

čista in preprosta. To olajša kasnejše preoblikovanje. Tokrat pa bi moral test biti uspešen.

Po potrebi preoblikujte kodo, da bo bolj jasna in lepša. Ta postopek ponavljajte, dokler ni

funkcionalnost implementirana in so vsi testi uspešni.

S TDD bomo lažje in hitreje pisali programsko kodo. Seveda bo ta koda tudi boljša – saj je

testirana – in enostavnejša – vsebuje samo to, kar potrebujemo. Boljša koda pa je

najpomembnejša, saj potrebuje malo vzdrževanja in je lažje prilagodljiva. Ob zagonu testa

takoj dobiš jasno povratno informacijo o uspešnosti. Takšen način razvoja postane hitro

samoumeven. Uspešni testi dajejo razvijalcem potrebno samozavest in spodbujajo

spremembe v kodi [4].

Slika 5: Primerjava klasičnega in TDD-cikla ter alternativ [7]

Page 27: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 15

Slika 6: TDD v osnovi [4]

2.6.3.1 Napiši test enote, ki pade

V prvem koraku v resnici naredimo dosti več, kot pa samo napišemo test. Sprejmemo

načrtovalske odločitve. Načrtujemo programski vmesnik (angl. Application Programming

Interface – API) – vmesnik do funkcionalnosti, ki ga testiramo. Na takšen način se

prisilimo, da dobro premislimo, kako bo ta koda uporabljena. Analogija je podobna kot pri

sestavljanju sestavljanke. Tam šele glede na ostale kose sestavljanke lahko določimo,

kateri kos manjka. Programerji smo uporabniki lastne programske kode, zato je zelo

pomembno, kako jo oblikujemo. Najboljše lahko ocenimo zasnovo tako, da jo začnemo

uporabljati. S pisanjem testov dosežemo ravno to – dobimo želeno povratno informacijo.

Pozornost je treba posvečati tudi granularnosti naših testov. Testi naj bodo čim manjši –

napišemo jih v nekaj minutah. Sama implementacija pa tudi ne bi smela presegati teh

časovnih okvirov. Razvoj s pomočjo testov je zelo učinkovit in zagotavlja modularno

kodo, ki je testirana [7].

Načrtovanje pa ne pomeni samo strukturiranja. Pomeni tudi prilagajanje programske

opreme trenutnim potrebam. Stranka naj definira, katere funkcionalnosti potrebuje zdaj.

Ostale se naj beležijo posebej in bodo implementirane, ko jih bo stranka potrebovala.

Na takšen način vedno gradimo tisto, kar se potrebuje in tako nadzorujemo aplikacijo in

njeno arhitekturo. Testi nas varujejo pred zastoji v razvoju, hkrati pa vidimo, v katero smer

moramo iti.

Page 28: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 16

2.6.3.2 Poskrbi, da bo test uspešen

V drugem koraku napišemo samo toliko izvorne kode, da bo test uspešno opravljen. Test,

ki pade, nam sporoča, da napisana koda ne počne tistega, kar se od nje pričakuje.

Implementacija običajno ne vzame več kot par minut in tako imamo kmalu spet delujoč

sistem.

Ena glavnih idej pri TDD je, da testi narekujejo, kaj je potrebno implementirati, da bomo

napredovali pri razvoju. Ne gre samo za pisanje izvorne kode. Potrebno je zadostiti

natančnim in nedvoumnim zahtevam, ki jih narekuje test. Uspešni testi so dokaz o

napredku pri razvoju.

Naš glavni cilj je, da naši testi kar se da hitro postanejo uspešni. To pogosto pomeni

izvorno kodo, ki je daleč od idealne. S tem se soočimo, ko smo dosegli želeno obnašanje in

nam tudi testi to potrjujejo [7].

2.6.3.3 Preoblikuj

Zadnji korak je, ko na našo zasnovo pogledamo nekoliko bolj od daleč in razmislimo, kako

bi jo izboljšali. Zaradi preoblikovanja nam TDD daje vzdrževano izvorno kodo. Brez tega

bi bil TDD samo dober način, kako ustvariti veliko kode, ki je sicer testirana, ampak zelo

grda. Takšna koda vpliva na našo produktivnost pri nadaljnjem delu z njo.. Napisani testi

dajejo zagotovilo, da s preoblikovanjem ne bomo česa pokvarili. Zato nikakor ne smemo

zanemarjati ali celo pozabiti na preoblikovanje [7].

Preoblikovanje je proces spreminjanja programske opreme na takšen način, da ne

spremenimo zunanjega obnašanja kode, ampak izboljšamo njeno notranjo strukturo. Je

priporočen način, kako očistimo kodo in zmanjšamo možnost za vnos novih napak. Pri

preoblikovanju izboljšamo arhitekturo kode, ki je že napisana [12].

Običajno se je najprej načrtovalo in potem kodiralo. Pri preoblikovanju pa delamo

nasprotno, lahko vzamemo slabo načrtovan oz. kaotičen sistem in ga spremenimo v dobro

oblikovan sistem. To naredimo z majhnimi koraki kot so: prestavimo kakšen atribut v drug

razred, izluščimo kakšno novo metodo ali prestavimo nekaj kode gor ali dol po razredni

hierarhiji. Skupen učinek teh malih sprememb lahko drastično izboljša obliko kode v

sistemu. Namen takšnega preoblikovanja je, da se izboljša razumljivost kode in olajša

nadaljnje delo z njo.

Page 29: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 17

Preoblikovanje je odgovor na spremembe pri implementaciji. Načrtovanje poteka ves čas

razvoja. Med gradnjo sistema se učimo, kako izboljšati obliko sistema. Na takšen način

dobimo programsko opremo, katere struktura je ustrezna celoten čas razvoja. Med

razvojem vedno bodisi dodajamo nove funkcionalnosti ali pa preoblikujemo že obstoječo

kodo. Česa se lotimo prej, je odvisno od naše ocene, kaj nam bo lažje. Brez preoblikovanja

se struktura programa postopoma slabša. Samo z branjem kode postane vedno težje videti

celotno sliko, kako je aplikacija načrtovana. Preoblikovanje pa je kot čiščenje in urejanje

kode. To slabšanje strukture pa je kot verižna reakcija, ki nas slej kot prej pripelje do

brezizhodne situacije. Dodajanje novih funkcionalnosti zahteva ogromno dela predvsem

zaradi podvajanja kode. Podvojena koda ne vpliva bistveno na hitrost izvajanja, a drastično

vpliva na njeno razumevanje in spreminjanje. Z odstranitvijo podvajanja zagotovimo, da je

koda jasna in edinstvena, kar pa je tudi bistvo dobrega načrtovanja.

Razvijalci pri pisanju kode vedno pozabljamo na možnost, da bo to kodo poleg nas bral oz.

uporabljal še kdo drug. V tem primeru je bolj kot optimalna koda pomembno, da je koda

berljiva in kar se da jasna. V nasprotnem primeru vzdrževanje tretje osebe zahteva občutno

preveč časa in napora. S preoblikovanjem lahko kodo naredimo bolj berljivo in tako

jasneje izraža svoj namen. Uporabimo pa ga lahko tudi v drugo smer. S preoblikovanjem si

pomagamo pri neznani kodi in jo postopoma oblikujemo glede na naše razumevanje. Tako

postopoma spoznavamo podrobnosti načrtovanja in dosežemo višjo stopnjo razumevanja

kot bi jo pa drugače. Z razumevanjem pa opazimo tudi skrite hrošče v kodi. Preoblikovanje

izboljšuje kvaliteto, načrtovanje, berljivost in hrošče v kodi. Logična posledica tega pa je,

da je razvoj hitrejši.

Pomembno pa je seveda vedeti, kdaj uporabiti preoblikovanje. Najpogosteje to naredimo,

ko moramo dodati kakšno novo funkcionalnost. V tem primeru preoblikujemo zaradi

boljšega razumevanja obstoječe kode ali pa ker nam obstoječa koda ne omogoča

enostavnega dodajanja. Na podoben način ga uporabimo tudi pri iskanju hroščev.

Preoblikujemo pa tudi pri pregledu kode, v kolikor je dovolj enostavno. Pregledi so

koristni za vse, saj se seznanijo z obstoječim in lahko predlagajo tudi kakšne popravke.

Običajno se to izvaja v manjših skupinah ali pa se programira v parih [12].

Page 30: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 18

2.6.4 Razvoj voden s prevzemnimi testi

Mamljivo je kar začeti pisati teste enot za našo aplikacijo, a takšnemu projektu manjka

ključna prednost TDD-metodologije. Kaj nam koristi odlična in testirana izvorna koda, če

je nikjer ne uporabimo ali pa se je ne da integrirati k ostalemu sistemu. Osnovno pravilo

TDD nam narekuje, da napišemo test, ki pade. Tako vemo, kje začeti oz. končati pisanje

izvorne kode.

Vsako novo implementacijo funkcionalnosti začnemo s pisanjem prevzemnega testa (Slika

7), ki odraža funkcionalnost, ki jo želimo dodati. Ko je test uspešen, smo končali. Takšna

praksa se imenuje – razvoj voden s prevzemnimi testi (angl. Acceptance Test Driven

development – ATDD). Prevzemni test nas vodi do situacije, ko bomo dejansko

potrebovali implementacijo, ki jo poskušamo dodati. Dodajamo samo tiste funkcionalnosti,

ki so dejansko potrebne. Znotraj prevzemnega testiranja pa imamo običajen TDD-razvojni

cikel. Zunanji cikel je prikaz dejanskega napredka, ki ga lahko pokažemo. Nabor testov pa

nas varuje pred napakami pri spreminjanju sistema. Običajno traja kar nekaj časa, da je

prevzemni test uspešen, zato običajno ločimo med prevzemnimi testi za funkcionalnosti, ki

jih šele razvijamo (niso vključeni v izdaje), in tistimi, ki so že končane (morajo vedno

delovati). Notranji cikel pa je namenjen razvijalcem. Pomaga vzdrževati kvaliteto kode.

Funkcionalnosti, katerih testi enot padejo, ne bi smelo biti v našem sistemu za upravljanje

konfiguracije [4].

Slika 7: Širši pogled na TDD oz. ATDD [4]

Page 31: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 19

Kadar je možno, pa naj prevzemni test preveri še sistem kot celoto, brez direktnega

klicanja notranjih funkcionalnosti. Takšen test celote komunicira z našim sistemom od

zunaj: preko uporabniškega vmesnika, pošilja sporočila kot drugi sistemi, kliče spletne

storitve, obdeluje izpise ipd. Celotno obnašanje sistema zajema tudi komunikacijo z

zunanjim okoljem. To je običajno najtežji in najbolj tvegan korak, zato ga pogosto

zanemarjamo. Običajno se izogibamo prevzemnim testom, ki preverjajo notranje delovanje

sistema, če je le možno. Opravimo jih samo, če želimo doseči pohitritev in že imamo nabor

testov za celoto.

Za nas celota pomeni več kot samo testiranje sistema od zunaj (Slika 8). Raje imamo, da

testiranje celote preveri tako sistem kot sam proces gradnje in namestitve. Vsak prispevek

v sistem za upravljanje konfiguracije naj bi občasno prenesel zadnjo verzijo sistema,

prevedel in testiral enote programske kode (avtomatizirana gradnja). Potem bi zadevo

integriral in zapakiral ter namestil v okolje, podobno pravemu. Na koncu pa bi še preveril

celoten sistem preko zunanjih dostopnih točk. To je precej dela, ampak mora biti storjeno

večkrat v življenjskem ciklu programske opreme. Veliko korakov tega cikla zahteva

spretnost in je podvrženo napakam, zato je idealen za avtomatizacijo [4].

Slika 8: Celotno razvojno okolje [6]

Sistem lahko namestimo, ko so vsi prevzemni testi uspešni. To naj bi nam dalo vedeti, da

vse deluje kot mora. Tukaj pa imamo še zadnji korak, to je produkcija. Sploh v večjih

podjetjih je gradnja namestitvenega sistema samo začetek izdaje sistema. Preden je sistem

na voljo končnim uporabnikom, ga običajno še testirajo (Slika 9), predajo posameznim

oddelkom in koordinirajo z ostalimi izdajami. Lahko pride tudi do drugih stroškov, ki niso

ravno tehnične narave. Izobraževanje, trženje in druge pogodbene obveznosti. To otežuje

cikel izdaj, zato moramo razumeti naše celotno tehnično in organizacijsko okolje [4].

Page 32: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 20

Slika 9: Preverjanje ustreznosti v agilnih moštvih [22]

2.6.5 Vedenjsko voden razvoj

Problem pri testiranju notranje strukture objekta je, da preverjamo, kaj objekt je, namesto,

da bi preverjali, kaj počne. Slednje je dosti bolj pomembno. Podobno velja tudi za

naročnike. Ne zanima jih, kako je kakšna stvar narejena, ampak da se končna aplikacija

obnaša tako, kot so pričakovali [39].

Vedenjsko voden razvoj (angl. Behavior driven development – BDD) se ne osredotoča na

strukturo, ampak na obnašanje. Takšen način pa se odraža na vseh stopnjah razvoja. Tako

se bolj osredotočamo na medsebojno delovanje: uporabnikov in sistema, objektov in na

koncu še med strukturami objektov. Komunikacija predstavlja enega večjih problemov v

razvojnih ekipah. BDD to rešuje s poenostavljanjem jezika, ki se uporablja za opisovanje

scenarijev (Slika 10), v katerih se bo aplikacija uporabljala. BDD spodbuja sodelovanje

med razvijalci, testerji in drugimi poslovnimi objekti. Osredotoča se na jasno zajemanje

zahtev o želenem obnašanju aplikacije, preko pogovora z naročniki. Testni primeri so

zapisani v naravnem jeziku, ki ga lahko razumejo vsi udeleženi. Gre za kombinacijo

naravnega jezika in jezika domene. Takšen zapis omogoča razvijalcem, da se osredotočijo

na razloge, zakaj se piše izvorna koda, ne pa na njene tehnične podrobnosti. Zmanjšuje

vrzel med jezikom domene in programskim jezikom, v katerem je aplikacija napisana [40].

Page 33: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 21

Slika 10: BDD-cikel [39]

BDD še ni bil formalno definiran. Opisujejo ga kot agilno metodologijo druge generacije,

ki izhaja iz uporabniškega vmesnika. Temelji na zahtevah, ki jih poda množica ljudi, ki jo

sestavljajo tako uporabniki kot naročniki. Proces je visoko avtomatiziran, produkt pa zelo

razširljiv. Opisuje komunikacijski cikel z dobro definiranimi rezultati, ki prinaša delujočo

programsko opremo, kot je bila zamišljena [40].

BDD predstavlja TDD, kakršen bi le-ta moral biti od samega začetka. Ne gre zgolj za

evolucijo, ampak obstaja tudi nekaj razlik. BDD zajema zahteve celotne aplikacije, ne pa

samo posameznih enot. Zahteve se zapišejo v obliki uporabniških zgodb. Ključno pa je

sodelovanje vseh vpletenih strani [41].

Principi BDD [39]

Dovolj je dovolj. Implementirano naj bo vse, kar je bilo zahtevano na samem

začetku. Kar je več, predstavlja potrato časa. To se nanaša tudi na avtomatizacijo.

Ne poskušajmo avtomatizirati vsega.

Dostavi vrednost. Ukvarjajmo se samo s tistimi stvarmi, ki naročniku prinašajo

korist ali pa nam povečujejo produktivnost za takšen razvoj.

Vse je obnašanje. Pa naj bo to na nivoju kode, aplikacije ali sistema. Za opis

obnašanja lahko uporabimo iste konstrukte ne glede na nivo.

Page 34: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 22

2.6.6 Eksperimentalno voden razvoj

Metodologiji TDD in BDD sta postali zelo razširjeni. Še vedno pa se lahko zgodi, da na

takšen način zamudimo kakšno poslovno priložnost ali celo, da kakšnega projekta ne

dokončamo. Ti dve metodologiji namreč ne moreta dati odgovora na sledeči vprašanji:

Kako se meri uporabnost aplikacije? Kako dobiti povratne informacije od uporabnikov?

Ankete niso pravi odgovor. Povratne informacije je potrebno dobiti na podoben način kot

ga ima TDD za kodo [42].

Eden glavnih problemov pri razvoju aplikacij je planiranje smernic nadaljnjega razvoja. Tu

imajo glavno vlogo različna subjektivna mnenja in nadrejeni. Takšne odločitve pa

zahtevajo dejstva, podprta s konkretnimi podatki. Vsako funkcionalnost predstavimo kot

hipotezo, zanjo napišemo eksperiment in jo pustimo, da zbira podatke v realnem okolju.

Dobljene informacije uporabimo za nadaljnji razvoj (Slika 11).

To pa je glavni cilj eksperimentalno vodenega razvoja (angl. Experiment driven

development – EDD). Gre za razvoj programske opreme, ki temelji na dejstvih. Vse se

začne pri idejah, na katerih se potem izvajajo meritve. Nič ni hipotetično, saj vse temelji na

dejanskih uporabnikih. Proces je iterativen. EDD pomaga določiti, katere funkcionalnosti

razviti in kam jih postaviti. Razkrije nam, kaj bo v prihodnosti postalo specifikacija. TDD

in EDD sta dobra naveza za kvalitetno in aktualno programsko opremo [42].

Slika 11: EDD-razvojni cikel [42]

Page 35: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 23

2.6.7 TDD in zastarela koda

Zastarela koda pomeni izvorno kodo, ki jo je napisal nekdo drug. Takšna koda pa zaudarja,

pa ne zato, ker bi bila stara, ampak ker je težko berljiva in verjetno vsebuje napake. Niti pa

ni možno vedeti, če smo s kakšno spremembo pokvarili kaj drugega. Sinonim za zastarelo

kodo je koda brez testov [7].

Večina razvijalcev ne dela na novih projektih, ampak vzdržuje, razvija dalje ali integrira

zadeve z že obstoječimi sistemi, ki so stari že tudi po več let ali celo desetletij. To pomeni,

da moramo TDD uporabljati na obstoječi izvorni kodi (Slika 12).

Proces je podoben kot pri projektih, ki se ne razvijajo po testih. Začnemo s pisanjem testa

za tisti del, ki ga hočemo spremeniti. To bo običajno pomenilo, da razdremo nekaj

odvisnosti brez testov, ki bi nam ščitili hrbet. Zaradi večje pazljivosti in učenja bomo na

začetku napredovali zelo počasi. To pa nas ne sme ustaviti, saj se bo razdiranje odvisnosti

in pisanje testov obrestovalo prej, kot si mislimo [7].

Slika 12: TDD in zastarela koda [7]

Proces je sestavljen iz treh faz [7]:

analiziranje sprememb,

priprave na spremembe,

testno voden vnos sprememb.

Page 36: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 24

Proces začnemo tako, da moramo v delujoč sistem vnesti neke spremembe. Ko poznamo

spremembo, gremo skozi vse tri faze procesa in tako dobimo nov delujoč sistem z

vnesenimi spremembami.

2.6.7.1 Analiziranje sprememb

Pri analizi sprememb moramo najprej določiti točke sprememb (angl. change points). To

so tiste točke, ki jih moramo spremeniti v izvorni kodi, da implementiramo želene

spremembe. Takšna analiza je v splošnem enaka, pa čeprav gre za zastarelo kodo ali pa ne.

Edina razlika je ta, da je zastarela koda težje razumljiva od tiste, ki je dokumentirana s

pomočjo testov enot.

Ko smo določili, kam bomo vnesli spremembe, moramo poiskati odvisne točke (angl.

inflection points). Pravimo jim tudi testne točke, to so takšne točke v naši kodi, kjer lahko

zaznamo spremembe v delovanju sistema, ko smo spreminjali kodo v točkah sprememb.

Običajno se odvisne točke nahajajo v bližnji okolici točk, kamor smo vnašali spremembe.

Seveda pa to ni nujno tako. Odvisne točke so lahko tudi daleč stran ali celo preko mreže v

drugem sistemu. Odločamo se med enostavnostjo pisanja testov in gotovostjo, ki nam jo ti

testi nudijo.

Bližnje odvisne točke predstavljajo lokalne kontrolne točke brez odvečnih motenj.

Oddaljene pa običajno ujamejo še kakšen stranski učinek, ki ga nismo zaznali z našo

analizo. V zameno pa je potrebno vložiti več truda v pisanje testov, ker nimamo takšnega

dostopa in natančnih informacij, kot pa bi jih imeli za bližnjo odvisno točko. Ko smo

določili točke sprememb in odvisnosti, vemo, kaj moramo spremeniti in kje lahko

testiramo obnašanje [7].

2.6.7.2 Priprave na spremembe

V tej fazi napišemo teste za odvisne točke in tako zabeležimo trenutno obnašanje, preden

vnesemo spremembe. To lahko vključuje tudi razbitje odvisnosti med objekti, ampak

moramo biti previdni in izpostaviti odvisnosti, da jih lahko kontroliramo v naših testih.

Teste, ki pokrivajo odvisne točke, tipično imenujemo karakterizacijski testi. To pomeni, da

preverjajo trenutno funkcionalnost takšno kot je, ne glede, če je obnašanje pravilno ali ne.

Uporabljajo pa se tudi za preverjanje domnev, ki smo jih postavljali pri identifikaciji točk

sprememb. S tem se odpravimo v zadnjo fazo procesa [7].

Page 37: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 25

2.6.7.3 Testno voden vnos sprememb

Ko smo zadovoljni s pokritostjo kode s testi odvisnih točk, dodamo še test za novo

funkcionalnost. Med samo implementacijo pa karakterizacijski testi (angl. characterization

tests) povedo, če smo karkoli pokvarili na obstoječi kodi, novi testi pa povedo, če smo

implementirali tisto, kar smo hoteli. Ob koncu, ko smo končali z implementacijo in so vsi

testi uspešni, pa varno preoblikujemo našo kodo, saj nas varujejo testi.

Glavna razlika v primerjavi z običajnim TDD-ciklom je, da moramo najprej napisati teste

za obstoječe obnašanje, potem šele za novo funkcionalnost. Pogosto pa moramo razbiti

tudi odvisnosti med objekti, pri katerih nas ne varujejo testi. To zahteva bolj natančno in

pazljivo delo [7].

2.6.8 Čista koda

TDD narekuje čim enostavnejšo in čisto programsko kodo. To pa seveda velja tudi za vse

ostale razvojne metodologije, saj smo se že vsi prevečkrat srečali s slabo in nepregledno

kodo. Čista koda je pomembna predvsem programerjem, ki neposredno delajo z njo. Vse

prevečkrat pa se zgodi, da preveč hitimo z implementacijo, bodisi zaradi rokov ali

preproste naveličanosti. Takšna koda je zelo težka za vzdrževanje, kar podaljša razvojne

cikle. Dodajanje novih funkcionalnosti pa ustvari še večji nered. Produktivnost začne

strmo padati in slej ko prej je potrebno zadevo načrtovati od začetka. Skrb za čisto kodo ni

le stroškovno učinkovita, ampak nujna, če hočemo preživeti kot razvijalci [11].

Najprej pa se moramo sploh vprašati, kaj čista koda sploh je? Definicija je drugačna za

vsakega razvijalca. Vzdrževanje čiste kode zahteva disciplino in uporabo nekaterih tehnik.

Vse je lažje, če imamo smisel za čisto kodo, v nasprotnem primeru pa se moramo

disciplinirati.

Koda naj bo elegantna in učinkovita. Jasno naj izraža logiko tako, da ni prostora za skrite

hrošče. Odvisnosti naj bodo minimalne, da je olajšano vzdrževanje, lovljenje napak

skladno z našo strategijo, hitrost pa blizu optimalne, da ne bodo drugi pokvarili kode z

nepotrebnimi optimizacijami. Čista koda dela samo eno stvar in to dobro.

Koda naj bo jasna in neposredna. Bere se naj kot dobro napisana proza. Nikoli ne skriva

programerjevih namer, ampak je polna abstrakcije in izraža jasno kontrolo.

Page 38: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 26

Čista koda se lepo bere in jo lahko izboljšajo tudi drugi razvijalci. Pokrita je s testi enot in

prevzemnimi testi. Vsebuje pomenska imena. Izraža samo en način dela za eno stvar. Ima

minimalne odvisnosti, ki so jasno določene, in ponuja čist in minimalen API.

Čista koda že na pogled daje jasno vedeti, da jo je napisal skrben razvijalec. Na njej ni nič

očitnega, kar bi klicalo po izboljšavi. Da delaš na čisti kodi, veš, ko se obnašanje vsake

prebrane rutine izkaže za pričakovano [11].

Vse skupaj pa bi lahko strnili v nekaj alinej [23]:

vsi testi so uspešni;

ni podvajanja, vse je potrebno izraziti dovolj jasno;

koda je izrazna – izraža vse načrtovalske ideje sistema; pomenska imena metod in

razredov, razbijanje razredov in metod na več delov;

minimalno število razredov in metod, hitra uvedba majhnih abstrakcij.

Vse to v kombinaciji s standardi kodiranja, formatiranjem in komentiranjem kode in

preoblikovanjem kode programerjem zelo olajša delo in pomaga k boljšemu končnemu

produktu v vseh pomenih besede.

2.6.9 Prednosti in slabosti TDD

Med samim razvojem sistema TDD daje povratne informacije o kvaliteti implementacije

(»Ali deluje?«) in kvaliteti arhitekture (»Je dobro načrtovano?«). Na takšen način imamo

dvojno korist.

Prednosti [4], [8], [9]:

večja produktivnost razvijalcev;

boljša kvaliteta kode;

test je izvršljiv opis – lahko ga poženemo – kaj programska koda dela in nam

narekuje ogrodje za implementacijo;

redka uporaba razhroščevalnika;

TDD je več kot samo vrednotenje sistema;

razvoj v majhnih korakih nudi boljši nadzor;

testiranje zagotavlja večjo samozavest razvijalcev;

testiranje nas opozori na napake zelo hitro, kar zmanjša čas razvoja in stroške;

Page 39: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 27

TDD vodi do bolj modularne, prilagodljive in razširljive kode ter manjših razredov

– rezultat tega so šibka sklopljenost in jasnejši vmesniki;

omogoča varno spreminjanje in dodajanje funkcionalnosti;

spodbuja ponovno uporabo in preoblikovanje kode;

večja možnost za uporabo načrtovalskih vzorcev, saj razvijamo v malih korakih;

enostavni testi poenostavijo pisanje kompleksne kode;

testi so najboljša dokumentacija in so ažurni;

testiranje preprečuje prekomeren razvoj, saj nam pove kdaj je neka funkcionalnost

dokončana;

večji poudarek na načrtovanju.

Pomanjkljivosti TDD [4], [8], [9]:

ni enostaven za začetnike, saj zahteva dosti vaje;

težko uporaben v okoljih, ki ne omogočajo popolne pokritosti s testi (uporabniški

vmesniki, podatkovne baze, omrežja, mobilne naprave);

težko je pridobiti podporo vodstva za TDD in jih prepričati, da pisanje testov ni

izguba časa;

slabo spisani testi postanejo velik problem pri vzdrževanju aplikacije;

stopnja pokritosti s testi in testiranje je težko ponovljivo v vsakem razvojnem ciklu

TDD – testi morajo biti ločeno popravljeni;

zaradi nedoslednosti se lahko pojavijo v naši kodi vrzeli – dobimo lažen občutek

uspešnosti;

razvijalec piše tako teste kot implementacijo. Vsaka napaka v razumevanju se tako

pojavi na dveh mestih;

veliko število uspešnih testov nam daje preveliko samozavest in se zato ne

poglobimo toliko v problematiko in druge vrste testiranj.

2.6.10 Testi kot dokumentacija

Dobro napisani testi enot so najenostavnejša oblika dokumentacije. Pravzaprav gre za

najboljšo možno dokumentacijo razredov. Pri TDD so testi sestavni del programske kode.

Dokumentacija ni več tako pomembna, saj se testi razvijajo skupaj s programom. Pisanje

testov se več kot izplača, saj za nekaj več vloženega truda dobimo kvalitetnejšo kodo in

manjšo potrebo po klasični dokumentaciji. Pri kvalitetnejši kodi pa seveda porabimo manj

Page 40: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 28

časa za iskanje hroščev. Testi enot so bolj natančni kot vsaka druga dokumentacija. Prav

tako so tudi bolj uporabni, saj nudijo informacije o tem, kako bi naj bi posamezen delček

kode deloval. Najboljše pri vsem tem pa je, da so ažurni. Če jih pišemo sproti, potem

odražajo vse spremembe, ki so bile narejene na programski kodi.

Seveda pa to ni nadomestilo za klasično dokumentacijo. Še vedno jo potrebujemo za naše

stranke ali zase. Testi pa so brez dvoma najboljša oblika sistemske dokumentacije, saj

najmanj motijo samo implementacijo. So praktični in kratki, saj se ne ubadajo s trivialnimi

stvarmi [16].

2.6.11 Zunanja in notranja kvaliteta

Na to, kaj nam testi povedo o sistemu, pa lahko gledamo tudi drugače. Ločimo med

notranjo in zunanjo kvaliteto (Slika 13). Zunanja kvaliteta pove, kako dobro sistem služi

naročniku in uporabnikom. Notranja kvaliteta pa nam pove, kako dobro sistem služi

razvijalcem (enostavnost in možnost spreminjanja). Prav tako kot zunanja pa je pomembna

notranja kvaliteta, a jo je težje doseči, saj nam ravno ta omogoča soočanje s stalnimi

spremembami. Zelo pomembno pa je, da jo ohranjamo, saj poenostavi spreminjanje

obstoječega sistema in zmanjša tveganje, da bodo spremembe zahtevale ogromno

prilagoditev [4].

Prevzemno testiranje celote daje jasnejšo sliko o zunanji kvaliteti sistema, pisanje teh

testov pa nam pove, kako dobro razvojna ekipa pozna problemsko domeno. Ne pove pa

nam ničesar o kvaliteti programske kode. Pisanje testov za enote zagotavlja veliko

povratnih informacij o kvaliteti same kode, njihov zagon pa nam pove, če smo pokvarili

kakšen razred. Ne povedo pa nič o ustreznosti celotnega sistema. Integracijsko testiranje pa

spada nekam vmes.

Da nam lahko testiranje enot pomaga pri notranji kvaliteti, morajo biti razredi dobro

strukturirani, da jih lahko testiramo neodvisno. Test enote mora ustvariti objekt in vse

njegove pomožne objekte, vse testirati in ugotoviti, če je obnašanje ustrezno. Odvisnosti

morajo biti eksplicitne, enostavno zamenljive, in metode jasne, da so enostavne za klicanje

in preverjanje. To pomeni, da mora biti koda šibko sklopljena in zelo vezljiva. To z

drugimi besedami pomeni, da je dobro načrtovana [4].

Page 41: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 29

Slika 13: Povratne informacije od testov [4]

Če se torej zadeve lotimo napačno in ne upoštevamo zgoraj napisanega, potem je pisanje

testov enot zahtevno in nerazumljivo. Programiranje po testu daje dragocene in takojšnje

povratne informacije o naši arhitekturi. V teh primerih nam pisanje testov ne diši, a vseeno

poskušamo. To pa je dobra priložnost, da natančneje pregledamo in popravimo

problematično strukturirano aplikacijo. Temu pravimo poslušanje testov [4].

2.6.12 Kaj testirati?

Test naj se napiše za vsako stvar, pri kateri se lahko karkoli zalomi. Običajno ne pišemo

testov za metode, ki vračajo ali nastavljajo vrednost nekega polja. Lahko pa jih, da se

prepričamo, če delujejo, sploh če so kompleksni. Ne pišemo jih niti za metode, ki samo

kličejo kakšno drugo metodo, če seveda ta klicana metoda ima test. V splošnem pa test

napišemo vedno, ko smo v dvomih. Boljše, da jih je preveč kot pa premalo. Napišemo jih

tudi preden gremo odpravljati kakšno napako, pomanjkljivost. Problem predstavljajo tudi

uporabniški vmesniki. Nemogoče jih je neposredno testirati s testi enot. Kar pa lahko

naredimo pa je, da kar se da ločimo poslovno logiko od uporabniškega vmesnika. Enako

velja tudi za spletne aplikacije. Na takšen način dosežemo solidno pokritost s testi. V

preteklosti pa so bile tudi težave pri testiranju na mobilnih telefonih, saj je bil pomnilniški

prostor omejen, orodja pa niso bila ustrezna. Oboje pa se je z leti spremenilo tako, da to

več ne predstavlja problema [16].

Page 42: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 30

2.6.13 Principi TDD

Predstavimo nekaj principov, pridobljenih z uporabo prakse TDD [6].

1. Profesionalni razvijalci testirajo svojo kodo.

2. Potrebno je ločiti med kaj (test) in kako (koda).

3. Z avtomatiziranimi testi potrdimo nove funkcionalnosti.

4. Gre za spremembo v kulturi.

5. Da program dela, ni dovolj.

6. Poslušajte, kaj vam govorijo testi.

7. Delujoč sistem daje povratne informacije.

8. Osredotočite se na namen.

9. Ko si v dvomih, se malo ustavi.

10. Bistvo ni samo testiranje.

11. Stara koda je koda brez testov.

12. Razumevanje principov, ki so za praksami.

Page 43: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 31

2.6.14 TDD-anti-vzorci

Pravi anti-vzorci se od slabih navad, praks in idej ločijo po tem, da posnemajo akcije,

procese ali strukture, ki se zdijo na prvi pogled koristni, a na daljši rok naredijo več škode

kot koristi. Vse to mora biti dokumentirano, preizkušeno v praksi in ponovljivo.

Tabela 2: Seznam anti-vzorcev [10]

Naziv Opis

Lažnivec

(The Liar)

Celoten test je uspešen za vse testne primere in deluje kot ustrezen, a ko boljše

pogledamo, ugotovimo, da sploh ne testira prave stvari.

Prekomeren trud

(Excessive Setup)

Test, ki zahteva veliko nastavljanja, da sploh lahko začnemo testiranje. Včasih

je potrebnih več sto vrstic kode, da se pripravi okolje za en test. Pri tem

sodeluje več različnih objektov, zaradi česar je težko preveriti, kaj se testira,

saj je zadeva nepregledna.

Velikan

(The Giant)

Test enote, ki sicer ustrezno testira objekt, a obsega preko tisoč vrstic in

vsebuje ogromno testnih primerov. To je lahko znak, da je testirani objekt

ogromen – vsemogočni objekt.

Namestnik

(The Mockery)

Včasih je nadomeščanje dobro in pride prav. Včasih pa se lahko razvijalec

izgubi v želji, da bi nadomestil vse, kar se ne testira. V temu primeru test

vsebuje toliko nadomestkov, ogrodij in ponaredkov, da se sploh ne testira tisto,

kar bi se moralo. V bistvu ti nadomestki vračajo tisto, kar naj bi se testiralo.

Inšpektor

(The Inspector)

Test enote, ki krši pravila ograjevanja z namenom, da bi dosegel 100 %

pokritost kode. Hkrati pa je tako prepleten z dejanskim objektom, da bo vsak

poskus preoblikovanja pokvaril test, vsaka sprememba na objektu pa mora biti

izražena v testu.

Nehvaležni ostanki

(Generous Leftovers)

Nek test generira podatke, ki so nekje shranjeni, drugi test pa te podatke

uporablja. Če je generiranje izvedeno na koncu ali pa ga sploh ni, bodo vsi

odvisni testi padli.

Lokalni junak

(The Local Hero)

Test, ki je odvisen od neke zadeve v razvojnem okolju. Test je uspešen na

razvojnih računalnikih, povsod drugje pa pade.

Nergač

(The Nitpicker)

Test, ki obdela celoten izhod podatkov, a v bistvu preverja le manjši delček

tega. Tako vedno obdeluje podatke, ki bi bili drugače nepomembni.

Najpogosteje pri testiranju spletnih aplikacij.

Tihi lovec

(The Secret Catcher)

Test, ki na prvi pogled sploh ničesar ne testira, saj ne vsebuje nobene izjave.

Problem pa se skriva v podrobnostih. Test se v resnici zanaša na izjemo, ki se

pojavi, ko pride do napake in pričakuje, da bo ogrodje za testiranje ujelo

izjemo in jo javilo kot napako.

Izmikant

(The Dodger)

Test, ki ima veliko testnih metod za manj pomembne dele, a nikoli ne testira

glavnih funkcionalnosti. Včasih se to pojavi pri testih dostopa do podatkovne

baze, kjer je klicana metoda, potem pa test prebere zapise iz baze in na njih

preverja izjave.

Gobcač

(The Loudmouth)

Test ali skupek testov, ki zapolnijo konzolo z diagnostičnimi sporočili,

dnevniškimi obvestili in drugimi nepomembnostmi tudi, ko je test uspešen.

Včasih testi niso ustrezno očiščeni tiste kode, ki ni več trenutno aktualna.

Požiralec

(The Greedy Catcher)

Test, ki lovi izjeme, a prekrije sled sklada. Včasih pa jo nadomesti z manj

informativnim sporočilom o napaki ali pa samo zapiše poročilo o napaki in test

uspešno konča.

Zaporedje

(The Sequencer)

Test, ki je odvisen od elementov neurejenega seznama, ki so v enakem

vrstnem redu pojavljajo v izjavah.

Page 44: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 32

Skrita odvisnost

(Hidden Dependency)

Podobno kot pri Lokalnem junaku test potrebuje pripravljene podatke, preden

se lahko izvede. V primeru, da teh podatkov ni, bo test padel in pustil malo

informacij o napaki, kar pomeni naporno branje kode in iskanje odvisnosti.

Števec

(The Enumerator)

Test, v katerem je vsaka testna metoda poimenovana z drugačno številko (npr.

test1, test2, test3). Namen teh metod ni jasen in zahteva dosti več truda, da se

seznanimo z njenim delovanjem.

OS promotor

(The Operating System

Evangelist)

Test, ki se zanaša na določen operacijski sistem, da lahko deluje. Dober primer

je Windows znak za novo vrstico, katerega test pade pod Linuxom.

Tujec

(The Stranger)

Testna metoda, ki sploh ne spada v test, v katerem se nahaja. V resnici testira

ločen objekt, običajno nek pomožni objekt. Metoda pa ga je testirala kot

samostojnega ne glede na njegovo odvisnost od glavnega objekta.

Srečko

(Success Against All

Odds)

Test, ki je bil napisan, da bi prvi uspel, ne pa prvi padel. Stranski učinek je ta,

da je vedno uspešen, tudi takrat, ko ne bi smel biti.

Šlepanje

(The Free Ride)

Namesto, da bi napisali novo testno metodo za novo funkcionalnost, raje kar v

obstoječo metodo dodamo par novih izjav.

Izbranec

(The One)

Kombinacija več vzorcev, običajno Velikan in Šlepanje, je test, ki vsebuje

samo eno testno metodo, ampak ta testira vse funkcionalnosti objekta.

Običajno se takšen test imenuje enako kot metoda, ki vsebuje več vrstic

nastavitev in izjav.

Nepovabljeni gost

(The Peeping Tom)

Test, ki zaradi deljenih virov lahko vidi rezultate drugega testa in tako

povzroči, da test pade, pa čeprav testirani sistem deluje čisto pravilno.

Običajno pri ogrodjih za testiranje, kjer se uporabljajo statične spremenljivke,

ki hranijo zbirke podatkov, in niso ustrezno počiščene.

Počasnež

(The Slow Poke)

Test, ki je izjemno počasen. Razvijalci imajo med izvajanjem čas za

vsakodnevne aktivnosti ali pa ga poženejo samo takrat, ko zaključijo delo.

Page 45: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 33

3 AVTOMATIZIRANO TESTIRANJE

Programska oprema mora biti testirana, da se prepričamo, da bo delovala tako kot mora v

svojem okolju. Testiranje mora biti učinkovito pri iskanju napak, testi pa kar se da hitri in

enostavni za izvajanje. Avtomatizacija testiranja lahko korenito zmanjša trud, ki je

potreben za ustrezno testiranje oz. poveča obseg testiranja v dani časovni enoti. Testiranje,

ki drugače traja več ur, se izvede v par minutah. Avtomatizirano testiranje lahko prihrani

veliko denarja (tudi do 80 %) ali pa omogoči hitrejši razvoj kvalitetnejše programske

opreme. Moderni testni režim omogoča testiranje s pritiskom na gumb, testi pa se izvajajo

ponoči, ko so računalniki običajno neizkoriščeni. Avtomatizirano testiranje je ponovljivo

in omogoča vedno enake vhodne podatke v enakem zaporedju. Tega ne moremo zagotoviti

z ročnim testiranjem. Z minimalnim naporom lahko izvedemo celotno testiranje. Bolj kot

je testiranje nadležno in dolgočasno, večja je potreba po ustreznih orodjih [13].

Samo testiranje je veščina, ki jo moramo osvojiti. Za vsak sistem obstaja ogromno število

testnih primerov, a imamo v omejenem času možnost pognati samo nekaj osnovnih. Teh

nekaj pa naj bi našlo kar se da veliko napak v programski opremi. Torej je izbira ustreznih

testnih primerov poglavitna. Izkušnje in eksperimenti so pokazali, da njihovo naključno

izbiranje ne obrodi sadov. Za dobre testne primere je potreben bolj temeljit pristop. Dober

testni primer določajo štirje faktorji (Slika 14). Verjetno najpomembnejši je učinkovitost

iskanja napak. Testni primer naj bi bil tudi primerno obsežen. Ostala dva faktorja pa sta

ekonomska. Koliko stane izvajanje, analiza in iskanje napak in kako je testni primer

razširljiv. To pomeni, koliko truda je potrebnega, da vnesemo nove spremembe.

Avtomatizacija testa je dražja kot pa enkratno ročno testiranje. Da bi z avtomatizacijo

pridobili, morajo biti testi previdno izbrani in implementirani. Kvaliteta avtomatizacije je

neodvisna od kvalitete testa. Avtomatizacija vpliva samo na stroške in razširljivost. Boljši

kot imamo pristop k avtomatizaciji, cenejša bo implementacija na dolgi rok. Večkrat ko bo

test pognan, več prihranimo v primerjavi z ročnim testiranjem. Za ustrezen in učinkovit

nabor testov je potrebno pazljivo izbrati in načrtovati teste, ki bodo preverjali

najpomembnejše stvari. Postopek izdelave in vzdrževanja pa naj bo kar se da enostaven in

z malo stroški. Znanje osebe, ki testira, določa kvaliteto testiranja [13].

Page 46: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 34

Slika 14: Faktorji avtomatiziranega testiranja [13]

3.1 Cilji avtomatiziranega testiranja

Vsi se lotimo avtomatiziranega testiranja z neko idejo, kaj bomo z njim pridobili. Poglejmo

si nekaj glavnih pridobitev. Prve tri predstavljajo koristi testiranja, zadnje tri pa se

osredotočijo na karakteristike samih testov [14].

3.1.1 Testi naj bi izboljšali kvaliteto

Običajno kvaliteto delimo v dve kategoriji, ki ju naslavljata vprašanji: Je programska

oprema grajena pravilno in ali smo razvili zahtevano programsko opremo? Temu pravimo

tudi verifikacija in validacija (angl. Verification and Validation – V&V). Če izvajamo

TDD, potem nam testi služijo kot specifikacije. Na ta način zapišemo, kaj mora sistem, ki

ga razvijamo, delati, še preden ga začnemo razvijati. Specifikacije zapišemo v izvršljivi

obliki in jih potem po želji poganjamo. Da se prepričamo, če razvijamo to, kar je

zahtevano, morajo naši testi natančno izražati, kako se bo sistem uporabljal. To lahko

dosežemo s skicami uporabniških vmesnikov, ki dajejo ravno dovolj informacij o izgledu

in obnašanju aplikacije, da lažje napišemo teste. Takšen način omogoča, da vse scenarije

premislimo in poiščemo področja, kjer so zahteve nejasne ali pa so si nasprotne. Boljše

specifikacije pa pomenijo boljši končni produkt [14].

Page 47: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 35

Testiranje je sicer iskanje napak, ampak to ni bistvo avtomatiziranega testiranja. Bistvo je,

da se že prej prepreči vnos napak. Takšno testiranje nas varuje pred novim vnosom napak v

programsko kodo, ki je bila pred spremembo ustrezna. Če ustrezno izvajamo regresijsko

testiranje, ne bi smelo priti do napak, saj jih bodo odkrili testi.

Sčasoma vedno pride do hroščev v programski opremi. Nekatere takšne napake je precej

težje preprečiti, kot pa popraviti. Če so testi ustrezno strukturirani, potem lažje določimo,

kje se nahaja napaka. To je ena glavnih prednosti testiranja enot pred prevzemnimi testi.

Prevzemno testiranje nam pove, da delovanje aplikacije ni v skladu z zahtevami naročnika,

testi enot pa nam povedo, zakaj je tako. Temu pravimo lociranje odpovedi. Vsega tega pa

ne moremo doseči, če ne pišemo testov za vse možne scenarije, ki naj bi jih neka enota

pokrivala. Podobno je tudi, če sami testi vsebujejo napake. Jasno je, da morajo naši testi

biti kar se da preprosti, da napake hitro opazimo [14].

3.1.2 Testiranje naj bi pomagalo razumeti sistem, ki ga razvijamo

Preprečevanje vnosa napak pa ni edina korist od testov. Branje testov nam tudi pove, kako

naj bi programska koda sploh delovala. Testi za črno škatlo so v bistvu specifikacije zahtev

za te komponente, ki jih testi pokrivajo. Na takšen način testi služijo kot dokumentacija.

Povedo namreč, kakšni bi morali biti rezultati. V primeru, ko pa hočemo videti postopek,

ki nas pripelje do teh rezultatov, pa lahko poženemo razhroščevalnik in teste in tako

postopoma pregledujemo kodo [14].

3.1.3 Testi naj bi zmanjšali tveganje

Poleg vnosa napak obstajajo še druga tveganja. Preveriti je potrebno tudi delovanje v

izrednih razmerah, do katerih ne more priti pri običajnem prevzemnem testiranju. Zelo

koristno je, če obdelamo vse možna tveganja in premislimo, katera tveganja lahko

ublažimo s pomočjo popolne avtomatizacije testov.

Pri delu z zastarelo kodo nimamo na voljo nabora avtomatiziranih testov, zato nikoli ne

vemo točno, kaj nam je vnesena sprememba pokvarila. To je tudi razlog, da delamo počasi

in skrbno. V primeru, ko pa takšna koda ima ustrezen nabor avtomatiziranih testov, lahko

delamo dosti hitreje. Dovoli nam tudi, da s kodo eksperimentiramo in tako hitreje

razumemo napisano kodo. Nabor avtomatiziranih testov služi kot varovalna mreža.

Učinkovitost te mreže je odvisna od tega, kako natančno testi pokrivajo obnašanje sistema.

Manjkajoči testi so kot luknje v tej mreži, nepopolne izjave pa kot natrgane vrvice.

Page 48: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 36

Vsaka takšna vrzel dovoli vnos napak, ki so različno nevarne. Mrežo dopolnjujejo tudi

aplikacije za upravljanje konfiguracije, ki omogočajo, da se vrnemo nazaj na različico, ki

je delovala. Za kratkoročne spremembe pa so na voljo orodja znotraj integriranega

razvojnega okolja (angl. Integrated Development Environment – IDE). Omogočajo

razveljavljanje zadnjih sprememb, vodijo nam pa tudi lokalno zgodovino datotek. Tako se

lahko vedno vračamo nazaj na želeno različico, ki je še ni v sistemu za upravljanje

konfiguracije (angl. Software Configuration Management – SCM) repozitoriju.

Seveda pa obstaja tudi možnost, da z avtomatiziranim testiranjem povečamo tveganje.

Pazljivi moramo biti, da si s tem ne nakopljemo novih problemov. Držati se je potrebno

načela, da logiko za testiranje ne mešamo s kodo, ki je za produkcijo. Na ta način se

izognemo vnosu zank, povezanih s testiranjem, v sistem, ki ga razvijamo. Vse kar je

povezano s testiranjem, naj se uporablja samo v okolju za testiranje. Druga nevarnost pa je,

da se zanašamo na kodo, ki naj bi bila temeljito testirana, a pravzaprav sploh ni bila. To se

zgodi, ko spreminjamo sistem, ki ga testiramo, tako da vnašamo logiko, ki se razlikuje

glede na test [14].

3.1.4 Testi naj bi bili enostavni za izvajanje

Pri razvoju aplikacij je testiranje kot nujno zlo. Razvijalci bodo teste poganjali dovolj

pogosto samo, če je to res enostavno opravilo. Test, ki ga lahko poženemo brez vsakega

ročnega vpletanja, je popolnoma avtomatiziran. Testi naj se sami preverjajo, to pomeni, da

preverijo, če je rezultat pričakovan. Večina ogrodij za testiranje ponuja grafične vmesnike,

ki nas z zeleno in rdečo barvo obveščajo o uspešnosti testiranja. Ponovljivost testov je

ključnega pomena. Pomeni, da bo vsak zagon testa vrnil čisto enak rezultat.

Neponovljivost je zelo nezaželena, saj zahteva obilo posredovanja razvijalcev. Enako

moteči pa so tudi nedoločeni testi (angl. Nondeterministic Tests), ki vedno vračajo različne

rezultate. To drastično zmanjša informativno vrednost rdeče črte. Namesto, da bi se takoj

lotili iskanja napake, jo ignoriramo, ko pa izgine, smo izgubili dragocene informacije o

napaki.

Testi, ki se izvajajo samo v pomnilniku in uporabljajo samo lokalne spremenljivke, so

običajno ponovljivi. Do problemov prihaja pri deljenih podatkih. V teh primerih moramo

poskrbeti, da testi počistijo za sabo. Najbolje je uporabiti kar splošen mehanizem za

uničevanje objektov, ki ga ponujajo ogrodja [14].

Page 49: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 37

3.1.5 Testi naj bi bili enostavni za pisanje in vzdrževanje

Pri pisanju programske kode moramo biti pozorni na celo kopico stvari. Pri pisanju testov

pa je bolje, če se osredotočimo na samo testiranje. To pomeni, da so testi enostavni za

pisanje in branje. To je zelo pomembno, saj je testiranje avtomatiziranih testov zapleteno

opravilo. Ker tega običajno ne delamo, je pomembno, da lahko napake hitro opazimo s

prostim očesom.

Seveda pa s spreminjanjem sistema vplivamo tudi na tiste teste, ki so povezani s

spremenjenim delom. To odvisnost želimo čim bolj zmanjšati. Določen del kode naj

pokriva samo en test, saj podvajanje testov nima pozitivnega učinka. Test naj bo majhen,

testira pa naj samo eno stvar naenkrat. To je še posebej pomembno za TDD, kjer vsak nov

test pokriva samo delček obnašanja celotnega sistema. Vse logične poti v kodi pa

pokrijemo z različnimi testnimi metodami. Izjema so testne metode, ki demonstrirajo

dejansko uporabo aplikacije. V primeru, da uporabnik naredi veliko korakov pri uporabi,

naj bo to vidno tudi v testni metodi. Vsak test mora jasno izražati svoj namen. Podobno kot

pri programski kodi se je tudi tukaj potrebno izogibati podvajanju.

Ločevanje odgovornosti (angl. Separation of Concerns) se izvaja na dva načina. Prvič,

testna koda naj bo ločena od končnega sistema, in drugič, da ima vsak test samo eno

odgovornost. Primer dvojne odgovornosti bi bil, če bi testirali poslovno logiko in grafični

vmesnik (angl. Graphical User Interface – GUI) v istih testih [14].

3.1.6 Testi naj bi zahtevali minimalno vzdrževanje

Spremembe so sestavni del razvoja aplikacij. Strmimo k temu, da bi nam testi omogočali

lažje spreminjanje programske kode in ne obratno. Zato naj bodo testi napisani kar se da

robustno, da ena sprememba vpliva na čim manj testov. To pomeni, da moramo zmanjšati

prekrivanje testov. Moramo pa se tudi prepričati, da sprememba v testnem okolju ne vpliva

na teste. To dosežemo z izolacijo testiranega sistema od testnega okolja [14].

Page 50: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 38

3.2 Manifest avtomatiziranega testiranja

Manifest izraža principe (kvalitete), ki naj bi jih testi imeli. Večina jih velja tako za

prevzemne test kot za teste enot [14]:

programiraj po testu (Write the Tests First),

načrtuj za testiranje (Design for Testability),

uporaba glavnih poti (Use the Front Door First),

izražaj namen (Communicate Intent),

izoliraj sistem, ki se testira (Isolate the System Under Test),

ne spreminjaj sistema, ki se testira (Don’t Modify the System Under Test),

testi naj bodo neodvisni (Keep Tests Independent),

minimiziraj prekrivanje testov (Minimize Test Overlap),

minimiziraj kodo brez testov (Minimize Untestable Code),

loči testno logiko od končnega sistema (Keep Test Logic Out of Production Code),

test naj preverja samo en pogoj (Verify One Condition per Test),

odgovornosti testiraj ločeno (Test Concerns Separately),

enači trud in odgovornost (Ensure Commensurate Effort and Responsibility).

3.3 Problemi pri avtomatizaciji

Pri avtomatizaciji pa se lahko pojavijo tudi problemi. Seveda je dobro, če jih poskušamo

malo napovedati, saj so čista presenečenja zelo nezaželena. To nam pomaga pri izdelavi

lastnega režima avtomatizacije. Seveda ne smemo imeti nerealnih pričakovanj, da bodo

orodja za testiranje rešila vse težave. Zavedati se je potrebno, da je še vedno treba vložiti

veliko truda, orodja so tu samo za pomoč. Sploh, če so pričakovanja vodstva res visoka,

takrat jih ne more uresničiti še tako dobro orodje. To še posebej velja, če nimamo ustrezno

urejenih praks testiranja. Najprej je potrebno izboljšati organizacijo in kvaliteto testov ter

dokumentacije. V tem primeru je boljše počakati z avtomatizacijo in najprej urediti

problematične zadeve [13].

Page 51: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 39

Ne smemo pričakovati, da bo zaradi avtomatizacije odkritih občutno več napak (Slika 15).

Gre samo za ponavljanje testov, napake se lahko najdejo samo s spremembo kode ali

spremenjenega okolja. Uspešni testi pa lahko tudi zavajajo oz. dajejo lažen občutek

varnosti. To lahko pomeni, da so testi nepopolni ali celo vsebujejo napake.

Slika 15: Stroški in povratne informacije napak pri različnih tehnikah testiranja [25]

Seveda je ves nabor testov potrebno tudi vzdrževati. Ob spremembah v sistemu je potrebno

spremeniti tudi nekatere teste, ki so postali neustrezni. Kadar je potrebno več truda za

spreminjanje testov, kot pa bi ga bilo potrebno za ročno poganjanje testov, bo

avtomatizacija opuščena. Treba je paziti, da avtomatizacija ne bo žrtev visokih stroškov

vzdrževanja.

Potrebno pa se je zavedati, da so orodja za avtomatizirano testiranje samo programi. Kot

takšni pa imajo lahko napake, zato vedno prihajajo nove različice teh orodij. Upoštevati je

potrebno tudi združljivost z razvojnimi orodji in aplikacijami, ki jih uporabljamo. Na voljo

je nešteto okolij, ki jih ta orodja morda ne podpirajo. Za maksimalno učinkovitost pa je

potrebno orodja obvladati. Tukaj govorimo o dodatnih izobraževanjih in učenju. Predpogoj

za uporabo teh orodij pa je, da je sistem, ki ga razvijamo, primeren za avtomatizirano

testiranje [13].

Page 52: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 40

Takšno avtomatizacijo pa seveda mora podpreti vodstvo, samo tako lahko postane sestavni

del organizacije. Čas je potrebno nameniti tudi izbiri orodij, izobraževanju,

eksperimentiranju in tudi učenju ter promociji uporabe teh orodij znotraj same

organizacije. Najboljše je, da obstaja znotraj organizacije nekdo, ki zelo dobro pozna

izbrano orodje. Takšna oseba potem širi znanje, promovira orodje in je na voljo za pomoč

ter ima glavno besedo pri izbiri orodja.

Avtomatizirano testiranje mora postati del razvojne infrastrukture, občasna uporaba ne

upraviči stroškov uvedbe. Pogosto se zgodi, da se avtomatizacija ne uporabi takrat, ko bi

bila najbolj koristna. To je pri spremembah in nadgradnjah aplikacij. Potrebno je poenotiti

testiranje znotraj celotne organizacije. V nasprotnem primeru pride do težav pri prenosu

testov med razvojnimi skupinami. Uporabo pa lahko zavirajo tudi administrativne zadeve

npr. premalo licenc za orodje. V primeru, da se testi izvajajo čez noč, je potrebno nameniti

nekaj delovnega časa pregledu rezultatov – ločena aktivnost. Pri ročnem testiranju je bil ta

čas skrit v samem poganjanju testov [13].

Naštejmo običajne razloge za neuspešnost pri avtomatizaciji testiranja [24]:

avtomatizacije ne moremo izvajati v prostem času, potrebna je večja

osredotočenost;

manjkajo jasno zastavljeni cilji;

manjkajo potrebne izkušnje;

pride do izgube izkušenj, ki smo jih pridobili pri ročnem testiranju;

k avtomatizaciji se zatekamo, ko smo obupani – rešitev naših težav je samo

pobožna želja in nima dosti skupnega z realnostjo;

napačno je mišljenje, da je poglavitna avtomatizacija in ne testiranje;

reševanje tehnoloških problemov lahko odvrne pozornost od testiranja;

programerji ne jemljejo avtomatizacije resno, še posebno takrat, ko imajo ločene

ekipe za testiranje;

zahtevno spoznavanje in učenje avtomatizacije testiranja ter pripadajočih orodij;

začetna investicija se ne povrne takoj. Tudi rezultati niso takoj vidni;

spremenljivost programske kode;

avtomatizacija testiranja zastarele kode;

strah zaradi neizkušenosti med programerji in tistimi, ki testirajo;

starih navad se je težko znebiti.

Page 53: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 41

3.4 Katere teste avtomatizirati?

V grobem lahko teste razdelimo v dve kategoriji (Slika 16) [14]:

funkcionalni testi (angl. functional tests) – preverjanje obnašanja sistema pri

različnih interakcijah;

celostni testi (angl. cross-functional tests) – preverjanje različnih vidikov sistema,

ki zajemajo več funkcionalnosti.

Slika 16: Vrste testov in način izvajanja [14]

Testiranje funkcionalnosti preverja konkretno obnašanje delčka programa. Funkcionalnost

je lahko povezana s poslovno logiko ali pa z zahtevami za delovanje (vzdrževanje sistema,

scenariji, odporni na napake). Večina teh zahtev je lahko izražena kot primer uporabe,

funkcionalnost, uporabniška zgodba ali testni scenarij. Testi funkcionalnosti se lahko ločijo

na poslovne (ali uporabniške) in pa na velikost sistema, ki mu pripadajo (Slika 17).

Prevzemni testi (angl. Acceptance, Customer, End-user tests) preverjajo obnašanje sistema

kot celote. Običajno ustrezajo primerom uporabe, funkcionalnostim ali uporabniškim

zgodbam. Razvijalci jih lahko avtomatizirajo, bistvo pa je, da lahko končni uporabnik

prepozna obnašanje tudi, če ne zna brati testov.

Testi enot (angl. Unit tests) preverjajo obnašanje posameznega razreda ali metode, ki je

bila načrtovana. Takšno obnašanje običajno ni direktno povezano z zahtevami, izjemoma

Page 54: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 42

pa tudi, če razred ali metoda vsebuje ključno logiko. Te teste pišejo razvijalci za lastne

potrebe – ostalim razvijalcem opišejo obnašanje v obliki testa.

Integracijski testi (angl. Component, Subsystem tests) preverjajo komponente, ki jih

sestavljajo razredi, ki skupaj tvorijo neko celoto. Po namenu sodijo med teste enot in

prevzemne teste.

Sejanje napak (angl. Fault insertion tests) poteka na vseh treh nivojih funkcionalnega

testiranja. Na vsakem nivoju se vstavijo različne vrste napak. Iz vidika avtomatizacije

testov je to samo še en skupek njihovih enot in integracije. Stvari postanejo bolj zapletene

pri aplikaciji kot celoti. Tukaj postane avtomatizacija zahtevna, kajti sejanje napak je

težavno, brez da bi nadomestili kakšen del aplikacije [14].

Zmogljivostni testi (angl. Performance tests) preverjajo nefunkcionalne zahteve sistema.

Zahteve so različne in lahko obsegajo različne funkcionalnosti. Običajno se nanašajo na

arhitekturo. Testira se lahko odzivne čase, kapaciteto in obremenitev. Večina teh testov

mora biti vsaj delno avtomatizirana, saj bi bilo ročno testiranje zelo težko. Ogrodje xUnit

ni preveč primerno za testiranje zmogljivosti, pa čeprav lahko teste izvajamo večkrat.

Prednost agilnih metod je, da lahko te vrste testov začnemo izvajati že kmalu v razvojnem

ciklu. Dovolj je, da so glavne komponente grobo sestavljene in da je ogrodje

funkcionalnosti možno pognati. Isti testi se lahko potem poganjajo stalno, ko se dodajajo

nove funkcionalnosti.

Testi uporabnosti (angl. Usability tests) preverjajo ujemanje z namenom in kontrolirajo, ali

so uporabniki aplikacije izpolnili zadane naloge. Takšne teste je zelo težko avtomatizirati,

saj zahtevajo subjektivno oceno uporabnikov o enostavnosti uporabe sistema.

Preiskovalno testiranje (angl. Exploratory testing) nam pove, ali je sistem konsistenten.

Testira se uporaba produkta, opazuje se obnašanje, tvorijo se hipoteze in načrtujejo se testi,

ki bodo preverili te hipoteze. Zaradi narave testiranja ti testi ne morejo biti avtomatizirani.

Lahko pa se avtomatizira priprava sistema, na katerem se izvaja preiskovalno testiranje

[14].

Page 55: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 43

Slika 17: Piramida testov (prirejeno po [38])

3.5 Testiranje enot

Testiranje enot je že dobro poznan in uveljavljen koncept pri razvoju programskih rešitev.

Poznan je že od začetkov programskega jezika SmallTalk okoli leta 1970. Od takrat pa se

vedno znova in znova dokazuje kot eden najboljših načinov, kako lahko razvijalec

izboljšuje kvaliteto kode in hkrati pridobiva znanje o funkcionalnih zahtevah razredov in

metod.

Test enote je delček kode (običajno je to metoda), ki pokliče neko drugo metodo in preveri

njeno delovanje v primerjavi s pričakovanim. V primeru, ko ni skladanja med dejanskim in

pričakovanim izhodom, test pade. Enoto predstavlja metoda ali funkcija. Delček kode, ki

se testira, se imenuje testiran sistem (angl. System Under Test – SUT). Delček kode, ki pa

testiranje izvaja, je testna metoda [27].

Poleg klasične definicije pa zapišimo še eno. Test enote je avtomatiziran del kode, ki kliče

različne metode in preveri pričakovane izhode logičnega obnašanja metode ali razreda, ki

se testira. Napisan je s pomočjo ogrodja za testiranje. Lahko se enostavno napiše in hitro

Page 56: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 44

požene. Požene ga lahko vsakdo v razvojni ekipi, večkrat zaporedoma. Logiko obnašanja

sestavljajo delčki kode, ki vsebujejo kakšno vrsto logike. Bodisi vejitve, zanke, kalkulacije

ipd [27].

Tehnike pri testiranju enot lahko v grobem delimo na tri tipe [28]: funkcionalno, strukturno

in hevristično testiranje. Napake v programski opremi se v splošnem delijo na nejasnosti,

presenečenja in napake pri implementaciji (Slika 18). Nejasnosti so zahteve, ki manjkajo

pri implementaciji. Presenečenja predstavlja implementacija, ki jo ne najdemo med

zahtevami. Napačno implementacijo pa predstavlja neustrezna implementacija zahteve.

Slika 18: Tipi testiranja enot in napake [28]

3.5.1 Testiranje in izolacija

Enote je najboljše testirati v popolni neodvisnosti od ostalih delov. Slej ko prej pa to ni več

možno. V tem primeru je treba dele, ki nas ne zanimajo, nekako nadomestiti (Slika 19).

Poznamo več načinov – uporabimo tistega, ki nam bolj ustreza [29].

Slepi (angl. Dummy) objekti se prenašajo naokoli, a niso nikoli uporabljeni.

Umetni (angl. Fakes) objekti so sicer delujoči, a je uporabljenih veliko bližnjic.

Ogrodja (angl. Stubs) se odzivajo samo na klice pri testiranju. Uporabljajo se tudi v

času, ko dejanska implementacija še ni na voljo.

Vohljači (angl. Spies) so ostanki, ki beležijo klice.

Nadomestki (ang. Mocks) so vnaprej pripravljeni objekti, ki imajo definirano

obliko klicev, ki bodo prejeti. V primeru napačnega klica lahko vrnejo izjemo ali pa

preverjajo, če so dobili vse pričakovane klice.

Page 57: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 45

Slika 19: Mreža objektov in testiranje z nadomestki [4]

3.5.2 Ogrodja za testiranje

Družina ogrodij xUnit za avtomatizirano testiranje je prilagojena uporabi pri avtomatizaciji

testiranja. Načrtovana so tako, da zadostijo naslednjim kriterijem [14]:

enostavno pisanje testov, brez da bi se bilo potrebno naučiti novega programskega

jezika;

enostavno testiranje posameznih razredov in objektov, preden imamo celotno

aplikacijo (omogoča testiranje od znotraj);

enostavno in hitro poganjanje testov;

minimizacija stroškov poganjanja testov.

Velika večina programskih jezikov ima tudi ogrodje za testiranje enot. V tabeli (Tabela 3)

so navedena nekatera ogrodja bolj znanih programskih jezikov. Veliko pa jih temelji na

ogrodju xUnit – v tabeli so označeni krepko. Testirati je mogoče objektne, imperativne,

logične, funkcijske, skriptne, označevalne, povpraševalne in paralelne jezike. Za testiranje

dostopa do baze pa se uporablja DbUnit. Testirati je možno tudi različne protokole.

Page 58: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 46

Tabela 3: Ogrodja za testiranje enot [26]

3.5.3 Poimenovanje testov

Za lažje iskanje in razumevanje je ključnega pomena, da teste ustrezno poimenujemo. S

sistematičnim poimenovanjem testnih metod je pokritost s testi lažje določiti. V imenu naj

bo tudi jasno viden pogoj, ki ga metoda testira. S pomočjo imen paketov, razredov in

metod poskušamo zajeti čim več uporabnih informacij. Naziv razreda in metode, ki se

testira, kakšna informacija o vhodnih vrednostih in po potrebi še kaj pomembnega o stanju

testiranega sistema. Tako je že iz nazivov jasno, kaj se testira in kakšni so testni pogoji.

Priporočljivo je tudi dodati kakšno informacijo o pričakovanih rezultatih testa [14].

S takšnim poimenovanjem testi služijo kot dokumentacija, kar pa je tudi ena od značilnosti

TDD. Dolžina teh nazivov je tako precej dolga, a to ni pomembno, saj teh metod nikjer ne

kličemo. So le del testnega nabora in se izvajajo avtomatično. Najprej lahko metodo

poimenujemo in potem napišemo njeno vsebino ali pa obratno [4].

Programski jezik Naziv ogrodja

ActionScript / Adobe Flex FlexUnit 4, AsUnit

Ada AUnit

ASP ASPUnit

BPEL BPELUnit

C C++test, CUnit

C++ CppUnit, UnitTest

Cobol COBOLUnit

Common Lisp CLUnit

Delphi DUnit

Fortran FUnit

FSharp FsTest

Groovy easyb

Haskell HUnit

Splet (Internet) HtmlUnit, HttpUnit, SOAtest

Java JUnit, Jtest

JavaScript JSUnit, jsUnitTest

LaTeX qsunit

LISP lisp-unit

Programski jezik Naziv ogrodja

MATLAB mlUnit

MySQL utMySQL

.NET NUnit, MSTest

Objective-C Kiwi, OCUnit

Object Pascal FPCUnit

Perl PerlUnit

PHP PHPUnit

PL/SQL utPLSQL, PLUTO

PostgreSQL PGUnit

Prolog PlUnit

Python PyUnit

Ruby RSpec

Scala ScUnit

Lupina (Shell) ShUnit

SmallTalk SUnit

SQL SQLUnit

XML XUnit

XSLT XSLTUnit

Page 59: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 47

Dogovor o poimenovanju testnih metod je zelo koristen. Priporoča se naslednja oblika:

[CiljnaMetoda]_[StanjeKiSeTestira]_[PričakovanRezultat]. Dejanski primer pa bi bil npr.

public void OdpriDatoteko_DatotekaJeNull_JaviIzjemoArgumentNull [30].

3.5.4 Struktura testa enote

Pisanje testov v standardni obliki pomeni lažje razumevanje. Tako so izjave in pričakovani

rezultati vedno na istem mestu v strukturi. Jasen znak slabega načrtovanja je, ko je test zelo

težko napisati v standardni strukturi. Glavni sestavni deli takšne strukture so [4]:

1. Priprava (angl. Setup) konteksta oz. okolja, v katerem bo izvršena ciljna metoda.

2. Izvršitev (angl. Execute) proži to ciljno kodo.

3. Preverjanje (angl. Verify) vidnega odziva, ki smo ga pričakovali.

4. Čiščenje (angl. Teardown) ostankov, da ne vplivajo na druge teste.

Pri pisanju testnih metod pa se je najboljše držati sintakse AAA. Na začetku pripravimo

vse potrebno za test (angl. Arrange). Nadaljujemo s proženjem metod, ki jih želimo

testirati (angl. Act). Za konec pa v izjavah preverimo ustreznost dobljenih rezultatov (angl.

Assert).

3.5.5 Pokritost kode s testi

Nabor testov enot služi kot varovalo, da z vnosom novih sprememb nismo česa pokvarili.

Problem pa nastane, ko se pri tem pokvari nekaj, kar ni bilo testirano. V ta namen je

potrebno natančno vedeti, katera koda se izvršuje v naših testih. Idealno bi bilo, če bi testi

pokrivali 100 % kode.

Testiranja po metodi črne škatle (testiranje brez poznavanja notranjega delovanja,

preverjajo se samo vhodi in izhodi) pokrivajo samo javno dostopne dele API-ja. Ker se

ravnamo po dokumentaciji, nimamo nobenega vpogleda v implementacijo. Tako ne

testiramo vseh možnih vejitvev v metodah. Samo testiranje metod pa je premalo. Zato je

bolj primerno testiranje po metodi bele škatle (testiranje notranjosti programa na način, da

preverimo čim več možnih poti). Z vpogledom v metodo lahko nadzorujemo tako vhode

kot tudi sekundarne objekte (nadomestke). To nam daje možnost, da poleg javnih

napišemo teste tudi za zaščitene in privatne metode, kar poveča pokritost kode s testi [31].

Page 60: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 48

Nekaj kriterijev za pokritost [32]

Pokritost funkcij – je bila klicana vsaka metoda v programu?

Pokritost izjav – se je izvedla vsaka izjava programa?

Pokritost odločitev – se izvede vsaka veja IF in CASE vozlišč?

Pokritost pogojev – so bile vse binarne izjave ovrednotene kot pravilne in napačne?

Pokritost pogojev in odločitev – kombinacija zgornjih dveh pokritosti.

3.6 Integracijsko testiranje

Integracijsko testiranje je faza testiranja programske opreme, pri kateri se kombinirajo

moduli (enote) in se potem skupaj testirajo. Eden od razlogov je lahko, da z nadomestki

nismo uspeli izolirati modula. Izvaja se za testiranjem enot in pred sistemskim testiranjem.

Za takšno testiranje se uporablja ogrodje xUnit ali FIT. Osnova za testiranje so moduli, ki

so že bili testirani. Povežemo jih v večje celote in nad njimi izvajamo integracijske teste. V

primeru, da so testi uspešni, je sistem pripravljen na sistemsko testiranje.

Namen testiranja je preveriti funkcionalne, zmogljivostne in zahteve glede zanesljivosti.

Skupki enot so testirani preko lastnih vmesnikov po metodi črne škatle s pomočjo

parametrov in vhodnih podatkov. Preverja se deljenje podatkov med več enotami in

medprocesna komunikacija. Posamezni podsistemi se preverjajo preko njihovih vhodnih

vmesnikov. Testni primeri so pripravljeni tako, da preverijo, če se vse enote v skupku

ustrezno sporazumevajo. Ideja je, da se postopoma dodajajo nove enote, ki so bile prej

testirane in se tako gradi vedno večja celota [33].

Vrste integracijskega testiranja [33], [37]

Veliki pok (angl. Big Bang) – skoraj vsi moduli so združeni v celoto in potem

testirani. Ta način prihrani veliko časa, če je ustrezno načrtovan.

Inkrementalni pristop (angl. Incremental Approach) – postopno združevanje

komponent.

Regresijsko testiranje (angl. Regression Testing) – preverja, da ob spremembah

niso bile vnesene nove napake.

Testiranje posledic (angl. Smoke Testing) – prvi test, ki se izvede ob prenovi oz.

razširitvi sistema.

Page 61: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 49

Od zgoraj navzdol (angl. Top-down) – najprej začnemo testirati zgornje module in

tako postopoma navzdol vse module.

Od spodaj navzgor (angl. Bottom-up) – najprej se testirajo komponente, ki so

najnižje v hierarhiji. To ponavljamo, dokler ne pridemo do komponent, ki so na

vrhu.

Hibrid je kombinacija zgornjih dveh vrst.

3.7 Sistemsko testiranje

Je del testnega razvojnega cikla in se izvaja pred prevzemnim testiranjem. Sistemsko

testiranje (Slika 20) se izvaja na končanem in integriranem sistemu, da se preveri skladnost

s specifikacijami. Gre za testiranje po principu črne škatle [47].

Vhod predstavljajo integrirani deli sistema, ki so uspešno opravili integracijsko testiranje.

Preverjajo se tako funkcionalne kot tudi sistemske zahteve. Gre za preiskovalno testno

fazo, kjer na destruktiven način poteka testiranje zasnove, obnašanja in celo predvidenih

pričakovanj naročnika. Na takšen način se preverja, če integrirani deli sistema delujejo in

komunicirajo med seboj tako, da zadostijo funkcionalnim zahtevam [47].

Število sistemskih testov je sorazmerno manjše kot pri integracijskem testiranju, saj naj bi

večino napak odkrili že testi v prejšnjih fazah testiranja (testiranje enot in integracije).

Stroški odprave napak, ki se pojavijo v fazi sistemskega testiranja, pa so seveda ustrezno

višji [46].

Slika 20: Sistemsko testiranje [47]

Page 62: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 50

Pod sistemsko testiranje pa spada tudi [47]:

funkcijsko testiranje (Functional testing),

GUI-testiranje (User interface testing),

testiranje uporabnosti (Usability testing),

testiranje združljivosti (Compatibility testing),

testiranje modelov (Model based testing),

testiranje izhodov ob napakah (Error exit testing),

testiranje pomoči uporabniku (User help testing),

testiranje varnosti (Security testing),

testiranje kapacitet (Capacity testing),

testiranje zmogljivosti (Performance testing),

testiranje racionalnosti (Sanity testing),

regresijsko testiranje (Regression testing),

testiranje zanesljivosti (Reliability testing),

testiranje obnašanja ob napakah (Recovery testing),

testiranje namestitve (Installation testing),

testiranje vzdrževanja (Maintenance testing) in

testiranje dostopnosti (Accessibility testing).

3.8 Prevzemno testiranje

Gre za testiranje po principu črne škatle, ki se izvaja nad celotnim sistemom. Vsak

posamezen test oz. uporabniški primer preverja določeno funkcionalnost ali uporabniški

pogoj. Rezultat takšnega testa je logična vrednost, pravilno ali narobe. Testno okolje je

običajno enako ali kar se da podobno pričakovanemu okolju končnih uporabnikov. Takšni

testi morajo biti opremljeni z vhodnimi podatki ali s formalnim opisom operacije, ki se

izvaja, da se lahko izvede test. Najboljše, če vsebuje kar oboje.

Teste običajno napišejo kar poslovni uporabniki v jeziku poslovne domene. To so končni

testi, ki preverijo popolnost implementiranih uporabniških zgodb. Idealno je, če teste v

sodelovanju napišejo poslovni uporabniki in analitiki, testerji ter razvijalci. Uspešna

izvedba teh testov daje stranki zagotovilo, da poteka razvoj v pravi smeri. Pomembno je,

da takšni testi vključujejo tako poslovno logiko kot tudi kontrolne elemente uporabniškega

Page 63: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 51

vmesnika. Kadar prevzemni test obsega več uporabniških zgodb, je potrebno neaktualne

nadomestiti. Uporabniška zgodba je zaključena, ko je pozitiven njen prevzemni test [34].

Tabela 4: Ogrodja za prevzemno testiranje [34]

Glavni cilj je, da se preveri, če sistem ustreza poslovnim zahtevam tako stranke kot

uporabnikov. To je tudi zadnja stopnja preverjanja kvalitete, kjer se pojavijo napake, ki so

prej ostale skrite. Ko so uspešni vsi prevzemni testi in je zadoščeno še morebitnim ostalim

prevzemnim pogojem, bodo naročniki odobrili plačilo projekta.

Tipi prevzemnih testiranj [34]

Uporabniško prevzemno testiranje s tovarniškimi uporabniki (angl. Factory Users)

ali uporabniki ob strani.

Operativno prevzemno testiranje preveri uporabnost in možnost vzdrževanja

sistema. To lahko obsega mehanizme za varnostno kopiranje, scenarije za

katastrofe, usposabljanje končnih uporabnikov, vzdrževalne in varnostne

procedure.

Pogodbeno in nadzorno prevzemno testiranje temelji na pogojih, zapisanih v

pogodbi in ostalih legalnih ter varnostnih pogojih.

Alfa testiranje se izvaja znotraj razvojnih skupin. Beta testiranje pa se izvaja pri

manjši skupini uporabnikov, ki potem nudijo povratne informacije razvijalcem.

Naziv ogrodja Programski jezik

Abbot Java

Concordion Java

Cucumber Ruby

FitNesse in Fit Java, .NET, C++, Delphi, Python, Ruby, Smalltalk, Perl

Frankenstein Java

ItsNat AJAX, Splet (Internet)

iMacros Splet (Internet)

Ranorex MFC, .NET, Java, Splet

RSpec Ruby

Selenium Splet (Internet), .NET, Java, Groovy, Perl, PHP, Phyton, Ruby

Test Automation FX .NET

Watir Splet (Internet)

Page 64: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 52

3.9 Vedenjsko testiranje

Takšno testiranje predstavlja svež pristop k razvoju programske opreme. Zahteve s

pomočjo jezika domene in nekaterih konstruktov opišemo v strukturiranemu načinu. To

predstavlja izvršljivo specifikacijo, ki je osnova za nadaljnji razvoj. Takšen način odpravlja

pomanjkljivost TDD, kjer je bila vrzel med testom in pripadajočo programsko kodo kar

nekoliko prevelika. Testi se potem izvedejo v ogrodju za testiranje enot.

Vedenjsko voden razvoj se začne s pogovorom med vsemi vpletenimi v razvoj. Na takšen

način se vsi seznanijo s funkcionalnostmi, ki bodo implementirane. Razjasnijo pa se tudi

morebitne nejasnosti v razumevanju. To zajema tudi pričakovane rezultate, ki nam jih te

funkcionalnosti dajejo. Ko jih implementiramo, vemo, da smo zaključili z delom na tej

funkcionalnosti.

Funkcionalnosti se zapišejo kot uporabniške zgodbe v malo bolj formalni obliki (Slika 21).

Slika 21: Uporabniška zgodba [39]

Ko smo se z zgodbo seznanili, se osredotočimo na scenarije, ki opisujejo obnašanje

sistema, kot jih pričakuje uporabnik. Scenarije sestavlja zaporedje korakov, zapisanih v

formalni obliki (Slika 22).

Slika 22: Oblika scenarija [39]

BDD-orodja delimo na xBehave (opis pričakovanja uporabnikov) in xSpec (opis

specifikacij na nivoju enote).

Page 65: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 53

Tabela 5: Seznam ogrodij za testiranje obnašanja [40]

Programski jezik Naziv ogrodja

C# SpecFlow, NSpec, MSpec, NBehave, Specter

F# TickSpec

Go Go Behave, GoSpec

Java JBehave, Instinct, JDave, Easyb, BDoc, Concordion

JavaScript Jasmine, BehaviourJS, JSpec

Objektni C Cedar

PHP Behad

Ruby RBehave, RSpec, Cucumber

3.10 A/B-testiranje

Osnovna ideja je primerjalno testiranje. Med seboj primerjamo več eksperimentov

(alternativ) in merimo uspešnost. Uporabimo ga lahko za predstavitev novih

funkcionalnosti, merjenje odziva na spremembe v starih funkcionalnostih, spremembah v

prikazu itd. Seveda lahko naenkrat primerjamo tudi več kot pa samo dve alternativi. Ideja

je, da se nove ideje predstavljajo uporabnikom v iteracijah. Njihov odziv pa narekuje

smernice razvoja [44].

Eksperimenti potem tečejo kot del aplikacije, ki jo razvijamo. Za prikazovanje alternativ

skrbi ogrodje tako, da so vse alternative prikazane enakomerno med uporabniki (Slika 23).

V ozadju se skrbno beleži vsa statistika teh alternativ in v vsakem trenutku je možno

pogledati poročilo stanja (Slika 24). Eksperimenti naj tečejo dovolj dolgo, da se izognemo

naključnim rezultatom. V primeru, da je katera od alternativ neprimerno bolj uspešna od

ostalih, je možno eksperiment zaključiti že predčasno [44].

Ta tehnika izhaja iz marketinga. Najbolj dodelano ogrodje za eksperimentalno voden

razvoj se imenuje Vanity in je napisano za programski jezik Ruby.

Page 66: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 54

Slika 23: A/B-testiranje [43]

Slika 24: Primer poročila EDD [42]

Page 67: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 55

4 SODOBNI KONCEPTI RAZVOJA PROGRAMSKIH REŠITEV

Na hitro preletimo koncepte sodobnih programskih rešitev, ki omogočajo enostavnejše

testiranje in razvoj. Te koncepte smo uporabili pri izdelavi praktičnega dela diplomske

naloge. Koncepti skupaj pokrivajo vse nivoje programskih rešitev in so tesno povezani s

TDD. Pravzaprav šele uporaba teh konceptov omogoča ustrezno testiranje in sodoben

razvoj programskih rešitev.

4.1 Vzorec MVVM

MVVM je arhitekturni vzorec (angl. Model-View-ViewModel – MVVM) (Slika 25) za

predstavitveni nivo aplikacije. Izhaja iz vzorca MVC in je namenjen WPF in Silverlight

aplikacijam. Omogoča jasno ločevanje med grafično predstavitvijo in poslovno logiko z

minimalno količino programske kode na predstavitveni strani [48].

Pogled (angl. View) predstavlja grafični vmesnik v jeziku XAML. Model predstavlja

podatkovni nivo oz. objektni model. Model in pogled pa povezuje vmesnik (angl.

ViewModel). Ta predstavlja podatkovni kontekst pogleda, odziva se na spremembe, izvaja

preverjanje podatkov in posluša dogodke.

Takšno ločevanje omogoča, da se grafični oblikovalec osredotoči na predstavitveni del,

razvijalec pa na poslovno logiko. Obstajajo tudi ogrodja MVVM, ki še izboljšajo razvoj, a

so zahtevna za uporabo. Tako razvito programsko rešitev je možno tudi enostavno testirati,

saj je vmesnik ločen od ostalih delov sistema [48].

Slika 25: Vzorec MVVM [48]

Page 68: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 56

4.2 Obrat kontrole

Obrat kontrole (angl. Inversion of Control – IOC) je v tesni povezavi z vrivanjem

odvisnosti. Formalna definicija pravi, da je IOC-vidik arhitekturnih rešitev, pri katerih je

kontrolni tok sistema obrnjen v primerjavi s tradicionalnim načinom. To v praksi pomeni,

da je kreiranje objektov prepuščeno ogrodju in ne programu, tako kot je bila praksa v

preteklosti. Vloge so zamenjane [50].

4.3 Vrivanje odvisnosti

Vrivanje odvisnosti (angl. Dependency Injection – DI) je načrtovalski vzorec, ki omogoča

razvoj šibko sklopljenih aplikacij. Namesto, da komponenti priskrbimo vse odvisne

objekte, raje samo vodimo seznam odvisnosti. Dobavo teh odvisnosti pa prepustimo

ogrodju za njihovo vrivanje, ki tako prevzame upravljanje celotnega življenjskega cikla

odvisnih objektov. Odvisnosti naj bodo predvsem vmesniki in ne konkretne

implementacije [49].

Tako razvita programska rešitev omogoča enostavno ponovno uporabo, lažje vzdrževanje,

testiranje in delo z nadomestki. Celotno aplikacijo drži skupaj samo nekaj vrstic kode, ki

povedo ogrodju, kako naj sestavi odvisnosti. Vrivanje izvede ogrodje, brez da bi določili

kdaj, kje, kako ali zakaj.

Obstaja več tipov vrivanja odvisnosti [49]:

preko konstruktorja,

preko lastnosti,

preko vmesnikov in

preko metod.

4.4 Stalna integracija

Je praksa razvoja programskih rešitev, pri kateri člani razvojne ekipe svoje delo pogosto

združujejo v celoto. Vsak član izvaja integracijo vsaj dnevno. To pomeni več integracij

celotne ekipe dnevno. Vsaka integracija se avtomatsko prevede, morebitne napake pa so

takoj vidne [51].

Page 69: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 57

Na takšen način se preverja, kako se posamezni deli rešitve skladajo med seboj. Vse to se

dogaja v okolju, ki je precej podobno produkcijskemu. Rešitev pa se vedno ohranja v

delujočem stanju. V primeru, da temu ni tako, se celotna ekipa posveti tej težavi.

Osnova za stalno integracijo (angl. Continuous integration – CI) je (porazdeljen) sistem za

upravljanje konfiguracije (angl. (Distributed) Version Control System – (D)VCS), katerega

sprememba proži CI-strežnik. Ta prenese zadnjo različico izvorne kode in jo prevede,

požene avtomatizirane teste vseh vrst, izvede analizo, preračuna metrike in podobno. Za

vse našteto izdela poročila in o rezultatih obvesti ekipo [51].

4.5 Načrtovalski vzorci

Pri razvoju programskih rešitev predstavljajo vzorci splošne rešitve za pogoste probleme

načrtovanja. Predstavljajo splošen opis ali predlogo rešitve, ki se lahko uporabijo v različne

namene. Namenjeni so predvsem objektno orientiranemu načinu programiranja [52].

Vzorci lahko pospešijo razvoj, saj prinašajo testirane in preverjene paradigme. Vzorci so

kombinacija dobrih praks in izkušenj, ki so jih sestavili eksperti.

Obstaja več tipov vzorcev [52]:

ustvarjalni vzorci,

strukturni vzorci,

vedenjski vzorci in

vzorci za večnitna okolja.

4.6 Principi SOLID

V objektno orientiranem programiranju SOLID predstavlja akronim za pet osnovnih pravil

OO-programiranja in načrtovanja. Tako razvite rešitve so enostavne za vzdrževanje in

nadgradnjo. Principi SOLID so kombinacija petih akronimov za principe: ena odgovornost

(angl. Single Responsibility Principle – SRP), odprtosti in zaprtosti (angl. Open Closed

Principle), Liskove zamenjave (angl. Liskov Substitution Principle), vmesniške ločitve

(angl Interface Segregation Principle) in obrata odvisnosti (angl. Dependency Inversion

Principle).

Page 70: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 58

Koncepti, ki jih principi promovirajo [53]:

vsak objekt naj ima samo eno odgovornost;

razredi naj bodo odprti za razširitve, a zaprti za spremembe;

menjava objektov z lastnimi podtipi naj ne vpliva na pravilnost programa;

vmesniki naj bodo specializirani in majhni;

uporaba abstrakcije namesto konkretnih objektov.

4.7 Praktični nasveti za programiranje in testiranje

Naštejmo nekaj dobrih praks, ki so se izkazale za uspešne pri načrtovanju in testiranju

programske opreme [35], [36]:

izogibajmo se operatorju »new«, raje uporabimo tovarne (Factory);

v konstruktorju naj bo samo inicializacija spremenljivk in nič drugega;

izogibamo se globalnim spremenljivkam;

vzorec Edinec (Singleton pattern) se naj uporablja redko;

izogibajmo se statičnim razredom, metodam in lastnostim;

dedovanje naj ne bo pregloboko; raje kompozicija kot dedovanje;

vejitve nadomestimo s polimorfizmom, če je možno;

uporaba vmesnikov (Interface) in ograjevanja (Encapsulation);

komunikacija in vedenje enot naj bo omejeno (Law of Demeter);

vrivanje odvisnosti (Dependency injection);

virtualne metode in lastnosti omogočajo lažje nadomeščanje (Mocking);

razredi naj imajo samo eno odgovornost (Single Responsibility Principle);

ločevanje poslovne logike od ostalih delov sistema (npr. vzorec MVVM ali MVC);

testi enote ne komunicirajo s podatkovno bazo, preko omrežja, z datotečnim

sistemom in ne potrebujejo posebne konfiguracije;

samo tista koda, ki je ni, je še boljša od enostavne kode;

minimalno število izjav na testno metodo – testi naj ne bodo odvisni med seboj;

uporaba konstant namesto magičnih nizov (angl. Magic strings);

ustrezno poimenovanje parametrov in metod;

izbira programskega jezika glede na domeno problema (DSL).

Page 71: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 59

5 PRAKTIČNI PRIMER RAZVOJA PO METODOLOGIJI TDD

Kot je bilo napovedano že v samem uvodu, bomo metodologijo TDD preizkusili tudi v

praksi. Najprej bomo predstavili idejo, nato pa še nabor orodij in funkcionalnosti, ki bodo

implementirane. Vse skupaj bomo zaključili z analizo dobljenih rezultatov in izkušenj.

5.1 Predstavitev in ideja

Ideja je, da se po metodologiji TDD razvije neka pilotska aplikacija. Razvoj naj bo podprt

s testi različnih nivojev (enot, integracije in sistema), ki bodo narekovali razvoj. Vse

glavne aktivnosti razvoja pa se bodo časovno merile za kasnejše analize.

Razvili bomo namizno aplikacijo za sledenje projektov. Omogočala bo meritve časa za

poljubne aktivnosti na projektu. Podatki bodo shranjeni v lokalni relacijski bazi, kar bo

omogočalo nemoteno delo tudi brez povezave v splet. Vse skupaj pa bo možno

pregledovati in analizirati s pomočjo izpisov. Grafični vmesnik pa bo kar se da enostaven

in prilagodljiv.

Osnovne funkcionalnosti aplikacije:

merjenje časa (štoparica),

registracija in urejanje uporabnikov,

urejanje meritev,

planiranje,

dodajanje opravljenega dela,

urejanje projektov in aktivnosti,

hramba podatkov (podatkovna baza),

o uporabniki, projekti, aktivnosti in meritve

pregled opravljenega dela,

izdelava poročil,

tiskanje in izvoz poročil,

obveščanje (pošiljanje elektronske pošte).

Page 72: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 60

5.2 Iteracija NIČ

Vsak projekt se začne z zbiranjem poslovnih in tehničnih zahtev. Preden lahko začnemo s

pisanjem programske kode, je potrebno postaviti ustrezno infrastrukturo, izbrati

programske platforme in pomožne knjižnice, ki se bodo uporabljali pri razvoju rešitve. Gre

za grobe odločitve, ki se kasneje še vedno lahko spremenijo, če se izkaže, da je bila ocena

napačna.

Tabela 6: Infrastruktura

Orodje Različica Opis

ClockingIT 0.99.3 Servis za meritve časa (http://www.clockingit.com/)

TeamCity 6.5.3 CI-strežnik

VisualSVN Server 2.1.9 SVN-strežnik

YouTrack 3.0.3 Sledenje napak in funkcionalnosti

Dobra infrastruktura (Slika 26) omogoča varnejši, hitrejši, kvalitetnejši in preglednejši

razvoj programskih rešitev.

Slika 26: Uporabljena infrastruktura

Page 73: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 61

Ob spremembi izvorne kode na SVN-strežniku se proži proces stalne integracije na CI-

strežniku TeamCity, ki ga sestavlja pet korakov.

Tabela 7: Koraki stalne integracije

Korak Opis

1. Prevajanje izvorne kode v načinu Release.

2. Izvedba testiranja na ogrodju NUnit in izračun pokritosti kode.

3. Statična analiza kode (FxCop).

4. Iskanje podvojene kode.

5. Analiza SVN-repozitorija in sprememb.

Programska oprema in komponente pa temeljijo na Microsoftovih tehnologijah ter na

priljubljenih odprtokodnih projektih. To zagotavlja razvijalcu podporo, primere,

dokumentacijo in združljivost.

Tabela 8: Seznam uporabljenih tehnologij

Tehnologija Različica Opis

.NET C# 4.0 Programsko ogrodje

DevExpress 11.1.6 Poročila

Entity Framework 4.1 Ogrodje za delo z bazo

Extended WPF Toolkit 1.5 Dodatne komponente

SQLCE 4.0 Podatkovna baza

WPF 4.0 Grafični vmesnik

Balsamiq Mockups 2.1.2 Skiciranje

Najbolje je izbrati tista orodja, ki jih priporoča agilna in TDD-skupnost. V .NET-okolju

izstopa predvsem orodje ReSharper, ki v zadnji različici še posebej olajša preoblikovanje

in delo s kodo. Za delo s knjižnicami in ogrodji je najboljše izbrati kar NuGet. To je

razširitev za Visual Studio, ki prevzame delo s knjižnicami. Dobra praksa je, da so te

knjižnice in ogrodja tudi del sistema za upravljanje konfiguracije. Na takšen način se

zagotovi konsistentnost paketov med razvijalci na različnih delovnih postajah. Nekatera

izmed uporabljenih orodij pa ne dodajajo novih funkcionalnosti, ampak samo omogočajo

lepši zapis ali prikaz.

Page 74: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 62

Tabela 9: Seznam uporabljenih orodij

Orodje Različica Opis

Debugger Canvas 1.0.3 Grafični vmesnik za razhroščevanje

dotCover 1.1.1 Pokritost kode s testi

Fluent Assertions 1.5 Lepša sintaksa izjav

Microsoft Visual Studio 2010, SP1 Razvojno okolje

Moq 4.0 Delo z nadomestki

Ninject 2.2.1.4 Vrivanje odvisnosti

NuGet 1.5 Delo s paketi (knjižnicami)

NUnit 2.5.10 Ogrodje za testiranje enot

ReSharper 6 Preoblikovanje in poganjanje testov

TortoiseSVN 1.6 SVN-ogrodje

VisualSVN 2.0.6 SVN-integracija za Visual Studio

Pomembna je tudi organizacija izvorne kode znotraj rešitve (Slika 27). Enote je potrebno

ločiti na ustrezne projekte in imenska področja.

Slika 27: Struktura rešitve

Page 75: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 63

Za programsko kodo, ki ima podobno zgradbo, si je priporočljivo narediti predloge. Slika

28 prikazuje predlogo in njeno uporabo. Predloga predpisuje poimenovanje in sintakso

AAA NUnit-testa.

Slika 28: Predloga in uporaba

5.3 Rešitev

Po metodi TDD smo razvijali knjižnico, ki vsebuje poslovno logiko celotne programske

rešitve. Knjižnica poleg poslovne logike zajema tudi podatkovni nivo. Predstavitveni nivo

ni pokrit s testi, saj povečini le kliče metode vmesnika v vzorcu MVVM.

Praktični razvoj je dobro začeti s skico uporabniškega vmesnika (Slika 29), saj tako poleg

problema dobimo še uporabniški pogled na rešitve.

Page 76: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 64

Slika 29: Skice vmesnikov

Potem se napiše enostaven test enote, ki predstavlja načrt programskega vmesnika, ki ga

bomo implementirali. Test poženemo (Slika 30), da se prepričamo, če pade. Šele potem

začnemo pisati programsko kodo. Vsake toliko počistimo za seboj in preoblikujemo

programsko kodo, da ustreza začrtanim smernicam razvoja.

Slika 30: Testi enot in pokritost kode

Nabor obsega 181 testov, od tega 126 testov enot, 49 integracijskih in 6 sistemskih testov.

Pokritost kode poslovnega in podatkovnega nivoja pa je 100 %.

Page 77: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 65

Za dostop do baze se uporablja vzorec repozitorij, ki izhaja iz domenskega načrtovanja in

se uporablja kot vmesni člen med domenskim modelom in podatkovno bazo. Predstavlja

objektno orientiran pogled na hrambo podatkov, kar omogoča testiranje ob ustrezni

uporabi nadomestkov (Slika 31).

Slika 31: Uporaba nadomestkov pri testiranju

S podatkovno bazo upravlja Entity Framework, ki omogoča pretvorbo podatkovnega

modela v relacijsko bazo. Razvijalec samo definira razrede in povezave, ogrodje pa jih

preslika v entitete in relacije (Slika 32). Nad podatkovnim modelom pa je možno uporabiti

tudi dedovanje.

Page 78: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 66

Slika 32: Entitetno relacijski model

Z uporabo vmesnikov in vrivanja odvisnosti dosežemo šibko sklopljenost med

komponentami sistema. Na takšen način razredi ne poznajo neposrednih povezav med

seboj (Slika 33).

Ogrodje za vrivanje odvisnosti in vzorec tovarniške metode pa poskrbita za izdelavo

objektov in vrivanje v konstruktorje, kjer se odvisnosti potrebujejo (Slika 34). Celotna

rešitev je dobesedno zlepljena v nekaj vrsticah kode. Ogrodje zna samo ustvariti konkretne

objekte, vmesnike pa je potrebno ročno povezati z ustreznimi objekti.

Page 79: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 67

Slika 33: Razredni diagram

Page 80: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 68

Slika 34: Vezava odvisnosti

Testi morajo biti preprosti, enako pa velja tudi za programsko kodo. Uporaba

razhroščevalnika zato naj ne bi bila pogosta. V primerih, ko pa je potreben, pa je dobro, da

se uporabi orodje, ki omogoča grafični prikaz poti v programski kodi. Na takšen način je

odkrivanje napak preglednejše in hitrejše.

Slika 35: Grafični prikaz poteka programa

Ob koncu implementacije nove funkcionalnosti najprej lokalno poženemo celoten nabor

testov. Izvorno kodo objavimo v SVN-repozitoriju samo v primeru, ko so vsi testi izvedeni

uspešno. To proži strežnik stalne integracije, ki podobno ponovi nad celotno programsko

rešitvijo v okolju, ki je podobno produkcijskemu (Slika 36).

Page 81: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 69

Slika 36: Strežnik stalne integracije

Končna aplikacija ima prilagodljiv grafični vmesnik, ki je praktičen in enostaven za

uporabo (Slika 37).

Slika 37: Del rešitve

Page 82: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 70

Strežnik stalne integracije pa vodi tudi nekaj lastnih statistik, ki poenostavijo spremljanje

razvoja projektov (Slika 38).

Slika 38: CI statistika

Page 83: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 71

6 ANALIZA

Med razvojem aplikacije smo skrbno beležili čas, ki smo ga porabili za posamezno

aktivnost.

Seznam aktivnosti, ki smo jih merili:

čas načrtovanja (analiza, učenje in načrtovanje),

implementacija (programiranje in oblikovanje),

pisanje testov,

popravljanje napak,

preoblikovanje in

vzdrževanja testov (popravljanje testov).

Za izvajanje meritev smo uporabljali spletno aplikacijo ClockingIT, ki omogoča enostavno

beleženje opravljenega dela (Slika 39).

Slika 39: Izpis dela na ClockingIT

Tabela 10: Meritve aktivnosti

Aktivnost Delovni čas Dejanski čas Trajanje [min] Porazdelitev

Vzdrževanje testov 4h 29min 4h 29min 269 4 %

Popravljanje napak 1d 1h 20min 9h 20min 560 9 %

Preoblikovanje 1d 4h 14min 12h 14min 734 12 %

Pisanje testov 1d 5h 23min 13h 23min 803 13 %

Načrtovanje 1d 5h 25min 13h 25min 805 13 %

Implementacija 1t 1d 3h 2min 2d 3h 2min 3062 49 %

Skupaj 2t 2d 7h 55min 4d 7h 53m 6233 100 %

Page 84: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 72

Za dejansko uporabo teh meritev je bilo zbrane vrednosti najprej potrebno preračunati v

dejanski čas. Beležili smo namreč delovni čas – 8h/dan oz. 40h/teden. Dobljeni dejanski

čas smo tako pretvorili v minute in prikazali časovno porazdelitev truda po aktivnostih

(Slika 40).

Slika 40: Delež truda po posameznih aktivnostih

Za primerjavo smo v literaturi poiskali podatke o štirih projektih in primerjali časovno

porazdelitev aktivnosti pri razvoju. Projekti predstavljajo eksperiment na dodiplomskih in

podiplomskih študijskih programih računalništva [55]. Ker se aktivnosti niso čisto ujemale,

smo jih smiselno združili. Pisanje in vzdrževanje testov smo združili v testiranje. Tudi

preoblikovanje ni bilo v najdenih virih merjeno kot ločena aktivnost. Merili pa smo pregled

(angl. review). Preoblikovanje in popravljanje napak smo združili z implementacijo,

preglede pa z načrtovanjem.

Projekt, razvit s testiranjem po implementaciji (angl. Test-Last Development – TLD), pa

predstavlja enak projekt, le da je razvit na klasičen način.

Tabela 11: Porazdelitev aktivnosti (prirejeno po [55])

Aktivnost Projekt #1

(dodiplomski)

Projekt #2

(podiplomski)

Projekt #3

(podiplomski)

Projekt #4 TLD

(dodiplomski)

Praktični

del

Testiranje 10 % 15 % 22 % 17 % 17 %

Načrtovanje 40 % 62 % 32 % 29 % 13 %

Implementacija 50 % 23 % 46 % 54 % 70 %

Tako združeni podatki omogočajo primerjavo časovnih porazdelitev aktivnosti (Slika 41).

4% 9%

12%

13%

13%

49%

Aktivnosti pri TDD

Vzdrževanje testov

Popravljanje napak

Preoblikovanje

Pisanje testov

Načrtovanje

Implementacija

Page 85: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 73

Slika 41: Primerjava časovnih porazdelitev TDD-projektov (prirejeno po [55])

10%

40%

50%

Projekt #1 (dodiplomski)

Testiranje

Načrtovanje

Implementacija

15%

62%

23%

Projekt #2 (podiplomski)

Testiranje

Načrtovanje

Implementacija

22%

32%

46%

Projekt #3 (podiplomski)

Testiranje

Načrtovanje

Implementacija

17%

13%

70%

Praktični del

Testiranje

Načrtovanje

Implementacija

Page 86: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 74

Primerjalni projekt so izvajali študenti v skupinah skozi celoten semester. Študenti niso

imeli preteklih izkušenj s programiranjem po testu. Razvidno je, da testiranje predstavlja

najkrajšo aktivnost. Razbrati je možno tudi, da se delež testiranja povečuje z izkušenostjo

razvijalcev. Izkušenejši namenijo dosti več časa testiranju. Pričakovano je tudi obratno

sorazmerje med implementacijo in načrtovanjem. Več časa kot je vloženega v načrtovanje,

krajša je implementacija.

Slika 42 prikazuje primerjavo časovne porazdelitve primerjalnega projekta razvitega po

metodi TLD in našega praktičnega dela.

Slika 42: Primerjava praktičnega dela s TLD (prirejeno po [55])

Dodiplomski študenti so morali za svoje projekte izdelati še dokumentacijo – od tod tudi

občutna razlika pri načrtovanju. Primerjalni projekti so bili razviti v Javi in manj

kompleksni kot naš praktični del. To je tudi razvidno iz trajanja testiranja in

implementacije.

Časovna porazdelitev zelo malo pove o obsegu rešitve. Za jasnejšo sliko moramo

primerjati metrike.

17%

29% 54%

Projekt #4 (dodiplomski - TLD)

Testiranje

Načrtovanje

Implementacija

17%

13%

70%

Praktični del

Testiranje

Načrtovanje

Implementacija

Page 87: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 75

Tabela 12: Primerjava metrik kode (prirejeno po [55])

Metrike kode Število

razredov Število

vrstic

[LOC]

Število vrstic

testov [TLOC] Vrstic kode

na metodo Pokritost

kode s testi

Projekt #1

(dodiplomski)

13 1053 168 12,1 28 %

Projekt #2

(podiplomski)

6 940 1999 22,38 92 %

Projekt #3

(podiplomski)

7 361 177 30,08 56 %

Projekt #4

(dodiplomski TLD)

4 259 38 7,4 25 %

Praktični del 29 775 828 3,91 100 %

Pokritost kode s testi je dosti višja pri izkušenejših razvijalcih. Razbrati je možno, da

metodologija razvoja zelo vpliva na pokritost kode s testi. Projekti razviti po TDD imajo

precej boljšo pokritost v primerjavi s TLD. Zanimivo je tudi, da so TDD-projekti dosegli

boljšo pokritost v krajšem času. Količina časa namenjenega testiranju se neposredno

odraža na pokritosti kode. Metodologija TDD sama po sebi ne zagotavlja majhnih razredov

in metod, implementacija je odvisna samo od razvijalcev.

Tabela 13: Primerjava metrik testov (prirejeno po [55])

Metrike testov TLOC/LOC Trditev/LOC Trditev/metodo Trditev/razred

Projekt #1

(dodiplomski)

0,16 0,03 0,32 1,00

Projekt #2

(podiplomski)

2,13 0,30 6,67 31,11

Projekt #3

(podiplomski)

0,49 0,12 3,75 4,50

Projekt #4

(dodiplomski TLD)

0,15 0,03 0,20 1,75

Praktični del 1,07 0,23 0,91 6,24

Večja pokritost kode s testi se izraža v večjem številu trditev (angl. Assertion) na

implementirano metodo. Število izjav je bistveno večje pri TDD-projektih. Izkušenejši

razvijalci, ki so dosegli zelo visoko pokritost, so napisali več kode za teste kot pa za

dejansko implementacijo. Daljše metode seveda potrebujejo več izjav, ki preverjajo

ustreznost.

Page 88: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 76

Slika 43 prikazuje izračunane metrike kode v razvojnem okolju Visual Studio. Število

vrstic kode celotne rešitve (brez grafičnega vmesnika) je okoli 2600. Indeks vzdrževanja za

knjižnice, ki so bile razvite s pomočjo TDD, je 89. To pomeni, da so enostavne za

vzdrževanje.

Slika 43: Metrike praktičnega dela v Visual Studiu

Tabela 14: Ostale metrike praktičnega dela

Metrika Vrednost

Vejitvena kompleksnost (povp.) 9,43

Globina dedovanja (povp.) 1,31

Razredna sklopljenost (povp.) 8,89

Število metod 198

Število izjav 534

Število trditev 181

Število trditev na testno metodo 1

Čas pisanja posameznega testa [min] 4,4

Napisanih testov na uro 13,51

Čas izvajanja vseh testov [s] 10

Vejitvena kompleksnost za posamezen razred se giblje med 1 in 20. Kar pomeni, da so

razredi sestavljeni iz enostavnih metod. Globina dedovanja posameznih razredov ne

preseže globine 4. Indeks razredne sklopljenosti pa se giblje med 1 in 50. Zgovorno je tudi

približno enako število vrstic kode med testi in implementacijo, ki jo ti testi pokrivajo.

Testi imajo več vrstic kode predvsem zaradi dodatnih metod, ki skrbijo za pripravo in

čiščenje za testi. V povprečju ena izjava na implementirano metodo pomeni, da smo

testirali samo željeno obnašanje (angl. Happy path).

Page 89: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 77

6.1 Zaključek

Iz podanih primerjav lahko sklepamo, da ni možno določiti vzorca časovnih porazdelitev

med začetnimi uporabniki metodologije TDD. Na porazdelitev vplivajo izkušnje

razvijalcev, poznavanje tehnologije in domene, natančnost specifikacij, uporabljena

metodologija, velikost razvojne skupine ipd.

Zelo zahtevno pa je tudi zbiranje podatkov o trajanju posameznih aktivnosti. Natančne

meritve praktično niso možne. Razlog tiči v agilnih metodologijah. V primerjavi s togimi

procesi razvoja so agilne metodologije zelo zabrisale prehode med posameznimi

aktivnostmi. Pri TDD je to še posebej očitno, saj se razvijalec stalno vrti med testiranjem,

implementacijo, preoblikovanjem in finim načrtovanjem (Slika 44). Prehodi med temi

aktivnostmi se dogajajo iz minute v minuto, zato je to zelo težko učinkovito meriti.

Slika 44: Primerjava TFP in TLD [55]

Razvijalci skladno z izkušnjami vlagajo čas v načrtovanje in testiranje. Rezultati tega so

neposredno vidni v trajanju implementacije. Rešitve razvite s TDD prinašajo večje število

napisanih testov. Več testov pa pomeni tudi večjo pokritost kode s testi. Razvijalci pa

dosežejo boljšo pokritost v krajšem času v primerjavi s TLD.

Pri notranji kvaliteti kode ni bilo mogoče zaznati vplivov metodologije. Kvaliteta kode je

odvisna predvsem od izkušenj razvijalcev in uporabljenih sodobnih konceptov razvoja

programskih rešitev.

Kombinacija načrtovanja in testiranja pri TDD pa zahteva svoj davek pri produktivnosti.

To sovpada s študijo, ki so jo naredili v podjetjih IBM in Microsoft [54]. Vsak projekt sta

ločeno razvijali različni ekipi. Rezultati kažejo, da so projekti, ki so bili razviti po metodi

TDD, trajali od 15–35 % več časa (Slika 45). Število napak pa je manjše za 39–91 %.

Ravno to pa najbolj zmanjšuje stroške razvoja programskih rešitev. Dobri rezultati niso

nujno posledica izbrane metodologije, lahko so samo posledica daljšega razvoja.

Page 90: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 78

Potrebno pa se je zavedati, da te ekipe sestavljajo vrhunski strokovnjaki, ki poznajo orodja,

principe, domeno in imajo ogromno izkušenj. Zato bi bilo podobne rezultate utopično

pričakovati v slabših razvojnih ekipah.

Slika 45: Študija o TDD [54]

Zunanja kvaliteta kode je izboljšana, saj pisanje testov razvijalcu pomaga boljše razumeti

problem. Boljše poznavanje domene pa vodi do rešitev, ki boljše služijo naročniku. Visoka

frekvenca poganjanja testov daje razvijalcu večjo samozavest, regresijsko testiranje pa ga

varuje pred vnosom novih napak. Posledica tega je manj napak v kodi, kar vpliva tudi na

zmanjšano uporabo razhroščevalnika. TDD pa razvijalcu tudi pomaga hitreje odpravljati

napake, saj napisan test zelo vpliva na razumevanje napake. Metodologija zahteva izkušnje

in disciplino. Za izkušene razvijalce je to načrtovalska, za neizkušene pa testirna tehnika.

Komu je namenjena, ni več dvomov, dejstvo pa je, da je vedno bolj priljubljena (Slika 46).

Slika 46: Trend razpisanih delovnih mest za TDD [56]

Page 91: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 79

7 SKLEP

Čeprav je metodologija testno vodenega razvoja stara že več kot desetletje, so jo razvijalci

začeli resno uporabljati šele pred nekaj leti. To ni nič čudnega, saj je potreben čas, da

skupnost razvije potrebna orodja in dobre prakse. Še vedno pa se razvija tudi sama

metodologija. Osnovo je predstavljalo programiranje po testu, ki je bila ena izmed praks v

ekstremnemu programiranju. Kasneje se je iz nje razvil testno voden razvoj, ki je z

dodanimi prevzemnimi testi postal razvoj voden s prevzemnimi testi. Vedenjsko voden

razvoj pa predstavlja trenutno zadnjo stopnjo. Vse različice so tesno povezane z

domenskim načrtovanjem, saj se dobro dopolnjujejo. Eksperimentalno voden razvoj pa ni

v širši uporabi, saj ni na voljo ustreznih orodij za posamezne jezike.

S širšo uporabo pa je testno voden razvoj postal kar nekakšen sinonim za profesionalne

razvijalce. V teoriji je metodologija precej preprosta, saj temelji na konceptih, ki so bili

znani že prej. Prednosti se najboljše vidijo v manjših agilnih moštvih, kjer se uporabljajo

sodobni koncepti razvoja programskih rešitev. V kombinaciji s stalno integracijo in

sodobnimi koncepti tvori lepo zaokrožen ekosistem, ki predstavlja inkubator za boljšo

programsko kodo.

Odzivnost na spremembe, razširljivost ter enostavnejše in cenejše vzdrževanje so le

nekatere od prednosti, ki jih prinaša. Testi predstavljajo ažurno dokumentacijo, regresijsko

testiranje pa preprečuje vnos novih napak. Od razvijalcev pa zahteva stalno učenje,

eksperimentiranje in disciplino.

Med razvojem praktičnega dela se je pokazala strma krivulja učenja. Brez poznavanja

praks in orodij je nemogoče začeti. Zato smo se morali najprej seznaniti z orodji in

koncepti, ki omogočajo načrtovanje rešitev s testiranjem v mislih. Tu gre za prakse, ki niso

strogo vezane na testno voden razvoj in bi jih moral poznati vsak resnejši programer.

Razvoj je trajal malo dlje časa, saj smo se prvič srečevali z metodologijo, orodji in tudi

tehnologijo, ki smo jo uporabili. Domena je predstavljala še najmanjši problem.

Za dobro poznavanje in uvedbo te metodologije znotraj organizacije je potreben čas. Zato

brez podpore vodstva zagotovo ne bo šlo. Samo s skupnimi močmi je možno doseči cilj –

razvoj boljših programskih rešitev z manj stroški. Potrebno je postaviti kvaliteto pred

kvantiteto. Tudi če naredimo samo kakšen testni projekt, se bodo dobljene izkušnje s

časom zagotovo obrestovale.

Page 92: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 80

8 VIRI

[1] Agilemanifesto, (2001), Manifesto for Agile Software Development, [Elektronski],

pridobljeno 25. 10. 2010, iz http://www.agilemanifesto.org/

[2] Extreme Programming, Extreme Programming: A gentle introduction,

[Elektronski], pridobljeno 8. 11. 2010, iz http://www.extremeprogramming.org/

[3] K. Auer, R. Miller, Extreme Programming Applied – Playing to win, Addison-

Wesley, 2002

[4] S. Freeman, N. Pryce, Growing Object-Oriented Software, Guided by Tests,

Addison-Wesley, 2010

[5] M. Feathers, S. Freeman, (2009), Test Driven Development: Ten Years Of Test

Driven Development, [Elektronski], pridobljeno 27. 11. 2010, iz

http://c2.com/cgi/wiki?TenYearsOfTestDrivenDevelopment

[6] M. Feathers, S. Freeman, Test Driven Development: Ten Years Later,

[Elektronski], [Video], http://www.infoq.com/presentations/tdd-ten-years-later

[7] L. Koskela, Test Driven Practical TDD and Acceptance TDD for Java Developers,

Manning, 2007

[8] Wikipedia, Test-driven development, [Elektronski], pridobljeno 3. 12. 2010 , iz

http://en.wikipedia.org/wiki/Test-driven_development

[9] Test Driven Development, [Elektronski], pridobljeno 3. 12. 2010, iz

http://www.c2.com/cgi/wiki?TestDrivenDevelopment

[10] J. Carr, TDD Anti-Patterns, [Elektronski], pridobljeno 9. 12. 2010, iz

http://blog.james-carr.org/2006/11/03/tdd-anti-patterns/

[11] R. C. Martin, Clean Code: A Handbook of Agile Software Craftsmanship,

Prentice Hall, 2009

[12] M. Fowler, K. Beck, J. Brant, W. Opdyke, D. Roberts, Refactoring: Improving

the Design of Existing Code, Addison Wesley, 1999

[13] M. Fewster, D. Graham, Software Test Automation Effective use of test

execution tools, ACM Press, Addison-Wesley, 1999

[14] G. Meszaros, xUnit Test Patterns - Refactoring Test Code, Addison Wesley, 2007

[15] K. Beck, C. Andres, Extreme Programming Explained: Embrace Change, Second

Edition, Addison Wesley, 2004

Page 93: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 81

[16] K. Beck, M. Fowler, Planning Extreme Programming, Addison Weley, 2000

[17] Wikipedia, Software development process, [Elektronski], pridobljeno 3. 11. 2010,

iz http://en.wikipedia.org/wiki/Software_development_process

[18] Wikipedia, Agile software development, [Elektronski], pridobljeno 13. 11. 2010,

iz http://en.wikipedia.org/wiki/Agile_software_development

[19] Wikipedia, History of software engineering, [Elektronski], pridobljeno 13. 11.

2010, iz http://en.wikipedia.org/wiki/History_of_software_engineering

[20] K. Beck, Extreme Programming Explained: Embrace Change, Addison Wesley,

1999

[21] G. Wiseman, Iterating and Incrementing to 'Get What You Need', [Elektronski],

pridobljeno 9. 12. 2010, iz http://www.infoq.com/news/2008/01/iterating-and-

incrementing

[22] Ambysoft, How Agile Are You?, [Elektronski], pridobljeno 20. 12. 2010, iz

http://www.ambysoft.com/surveys/howAgileAreYou2010.html

[23] R. Jeffries, Essential XP: Emergent Design, [Elektronski], pridobljeno 25. 12.

2010, iz http://xprogramming.com/classics/expemergentdesign/

[24] C. Lisa, G. Janet, Agile Testing – A Practical Guide for Testers and Agile Teams,

Addison-Wesley, 2009

[25] Ambysoft, Why Agile Software Development Techniques Work: Improved

Feedback, [Elektronski], pridobljeno 11. 2. 2011, iz

http://www.ambysoft.com/essays/whyAgileWorksFeedback.html

[26] Wikipedia, List of unit testing frameworks, [Elektronski], pridobljeno 24. 2. 2011,

iz http://en.wikipedia.org/wiki/List_of_unit_testing_frameworks

[27] R. Osherove, The Art Of Unit Testing With Examples In .NET, Manning, 2008

[28] R.V. Rajendran, White paper on Unit Testing, [Elektronski], pridobljeno 25. 2.

2011 iz http://www.mobilein.com/WhitePaperonUnitTesting.pdf

[29] G. Meszaros, TestDouble, [Elektronski], pridobljeno 26. 2. 2011 iz

http://martinfowler.com/bliki/TestDouble.html

[30] J. H, Oh, so that’s why you people have such long unit test names, [Elektronski],

pridobljeno 28. 2. 2011 iz http://jacksonh.tumblr.com/post/963132661/oh-so-thats-

why-you-people-have-such-long-unit-test

[31] P. Tahchiev, F. Leme, V. Massol, G. Gregory, JUnit in Action, Second Edition,

Manning, 2008

Page 94: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 82

[32] Wikipedia, Code coverage, [Elektronski], pridobljeno 2. 3. 2011, iz

http://en.wikipedia.org/wiki/Code_coverage

[33] Wikipedia, Integration testing, [Elektronski], pridobljeno 2. 3. 2011, iz

http://en.wikipedia.org/wiki/Integration_testing

[34] Wikipedia, Acceptance testing, [Elektronski], pridobljeno 4. 3. 2011, iz

http://en.wikipedia.org/wiki/Acceptance_testing

[35] Google Testing Blog, Writing Testable Code, [Elektronski], pridobljeno 11. 5.

2011, iz http://googletesting.blogspot.com/2008/08/by-miko-hevery-so-you-

decided-to.html

[36] Stackoverflow, Writing »unit testable« code?, [Elektronski], pridobljeno 11. 5.

2011, iz http://stackoverflow.com/questions/1007458/writing-unit-testable-code

[37] B. B. Agarwal, S. P. Tayal, M. Gupta, Software Engineering & Testing, Jones

and Bartlett Publishers, 2010

[38] T. Riley, A. Goucher, Beautiful Testing, O’Reilly, 2010

[39] D. Chelimsky, The RSpec Book – Behaviour-Driven Development with RSpec,

Cucumber, and Friends, The Pragmatic Bookshelf, 2010

[40] Wikipedia, Behavior Driven Development, [Elektronski], pridobljeno 19. 5. 2011,

iz http://en.wikipedia.org/wiki/Behavior_Driven_Development

[41] N. Lakshminarayan, BDD is more than »TDD done right«, [Elektronski],

pridobljeno 19. 5. 2011, iz http://neelnarayan.blogspot.com/2010/07/bdd-is-more-

than-tdd-done-right.html

[42] S. Auvray, Experiment Driven Development - The Post-Agile Way, [Elektronski],

pridobljeno 20. 5. 2011, iz http://www.infoq.com/news/2010/02/edd-post-agile

[43] P. Chopra, The Ultimate Guide To A/B Testing, [Elektronski], pridobljeno 20. 5.

2011, iz http://www.smashingmagazine.com/2010/06/24/the-ultimate-guide-to-a-b-

testing/

[44] A. Arkin, Vanity: Experiment Driven Development for Rails, [Elektronski],

pridobljeno 20. 5. 2011, iz http://vanity.labnotes.org/

[45] InfoQ, Domain-DrivenDesign Quickly, [Elektronski], pridobljeno 1. 8. 2011, iz

http://www.infoq.com/minibooks/domain-driven-design-quickly

[46] A. Ramdeo, System Testing, [Elektronski], pridobljeno 2. 8. 2011, iz

http://www.testinggeek.com/system-testing

Page 95: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 83

[47] KabInfo, Learn System Testing, [Elektronski], pridobljeno 2. 8. 2011, iz

http://www.kabinfo.net/kabinfol_SystemTesting.asp

[48] P. Dhawan, Step By Step Guide To MVVM, [Elektronski], pridobljeno 2. 8. 2011,

iz http://www.codeproject.com/KB/WPF/StepByStepGuideToMVVM.aspx

[49] Wikipedia, Dependency injection, [Elektronski], pridobljeno 2. 8. 2011, iz

http://en.wikipedia.org/wiki/Dependency_injection

[50] G. Patel, IOC (Inversion of control) Basics With Example, [Elektronski],

pridobljeno 2. 8. 2011, iz http://www.goospoos.com/2009/12/inversion-of-control-

basics-with-example/

[51] J. Humble, D. Farley, Continuous Delivery: Reliable Software Releases through

Build, Test and Deployment Automation, Addison-Wesley, 2011

[52] Wikipedia, Design pattern, [Elektronski], pridobljeno 3. 8. 2011, iz

http://en.wikipedia.org/wiki/Design_pattern_(computer_science)

[53] R. C. Martin, The Principles of OOD, [Elektronski], pridobljeno 3. 8. 2011, iz

http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod

[54] Typemock, The Cost of Test Driven Development, [Elektronski], pridobljeno 11.

8. 2011, iz http://blog.typemock.com/2009/03/cost-of-test-driven-development.html

[55] D. S. Janzen, An Empirical Evaluation of the Impact of Test-Driven Development

on Software Quality, [Elektronski], pridobljeno 30. 8. 2011, iz

http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.94.9412&rep=rep1&type

=pdf

[56] Indeed, Indeed – one search, all jobs, [Elektronski], pridobljeno 31. 8. 2011, iz

http://www.indeed.com/

Page 96: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 84

9 PRILOGE

9.1 Seznam slik

Slika 1: Prakse ekstremnega programiranja [20] .................................................................. 6

Slika 2: Prakse pri XP2 [15] .................................................................................................. 7

Slika 3: Razvoj v ciklih in odvisnosti med njimi [9] ........................................................... 11

Slika 4: Inkrementalni in iterativni razvoj [21] ................................................................... 12

Slika 5: Primerjava klasičnega in TDD-cikla ter alternativ [7] ........................................... 14

Slika 6: TDD v osnovi [4] ................................................................................................... 15

Slika 7: Širši pogled na TDD oz. ATDD [4] ....................................................................... 18

Slika 8: Celotno razvojno okolje [6] ................................................................................... 19

Slika 9: Preverjanje ustreznosti v agilnih moštvih [22] ...................................................... 20

Slika 10: BDD-cikel [39] .................................................................................................... 21

Slika 11: EDD-razvojni cikel [42] ...................................................................................... 22

Slika 12: TDD in zastarela koda [7] .................................................................................... 23

Slika 13: Povratne informacije od testov [4] ....................................................................... 29

Slika 14: Faktorji avtomatiziranega testiranja [13] ............................................................. 34

Slika 15: Stroški in povratne informacije napak pri različnih tehnikah testiranja [25] ....... 39

Slika 16: Vrste testov in način izvajanja [14] ..................................................................... 41

Slika 17: Piramida testov (prirejeno po [38]) ...................................................................... 43

Slika 18: Tipi testiranja enot in napake [28] ....................................................................... 44

Slika 19: Mreža objektov in testiranje z nadomestki [4] ..................................................... 45

Slika 20: Sistemsko testiranje [47] ...................................................................................... 49

Slika 21: Uporabniška zgodba [39] ..................................................................................... 52

Slika 22: Oblika scenarija [39] ............................................................................................ 52

Page 97: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 85

Slika 23: A/B-testiranje [43]................................................................................................ 54

Slika 24: Primer poročila EDD [42] .................................................................................... 54

Slika 25: Vzorec MVVM [48] ............................................................................................. 55

Slika 26: Uporabljena infrastruktura ................................................................................... 60

Slika 27: Struktura rešitve ................................................................................................... 62

Slika 28: Predloga in uporaba .............................................................................................. 63

Slika 29: Skice vmesnikov .................................................................................................. 64

Slika 30: Testi enot in pokritost kode .................................................................................. 64

Slika 31: Uporaba nadomestkov pri testiranju .................................................................... 65

Slika 32: Entitetno relacijski model..................................................................................... 66

Slika 33: Razredni diagram ................................................................................................. 67

Slika 34: Vezava odvisnosti ................................................................................................ 68

Slika 35: Grafični prikaz poteka programa.......................................................................... 68

Slika 36: Strežnik stalne integracije .................................................................................... 69

Slika 37: Del rešitve ............................................................................................................ 69

Slika 38: CI statistika ........................................................................................................... 70

Slika 39: Izpis dela na ClockingIT ...................................................................................... 71

Slika 40: Delež truda po posameznih aktivnostih ............................................................... 72

Slika 41: Primerjava časovnih porazdelitev TDD-projektov (prirejeno po [55]) ................ 73

Slika 42: Primerjava praktičnega dela s TLD (prirejeno po [55]) ....................................... 74

Slika 43: Metrike praktičnega dela v Visual Studiu ............................................................ 76

Slika 44: Primerjava TFP in TLD [55] ................................................................................ 77

Slika 45: Študija o TDD [54] ............................................................................................... 78

Slika 46: Trend razpisanih delovnih mest za TDD [56] ...................................................... 78

Page 98: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 86

9.2 Seznam tabel

Tabela 1: Mejniki TDD [5, 6] ............................................................................................... 9

Tabela 2: Seznam anti-vzorcev [10] .................................................................................... 31

Tabela 3: Ogrodja za testiranje enot [26] ............................................................................ 46

Tabela 4: Ogrodja za prevzemno testiranje [34] ................................................................. 51

Tabela 5: Seznam ogrodij za testiranje obnašanja [40] ....................................................... 53

Tabela 6: Infrastruktura ....................................................................................................... 60

Tabela 7: Koraki stalne integracije ...................................................................................... 61

Tabela 8: Seznam uporabljenih tehnologij .......................................................................... 61

Tabela 9: Seznam uporabljenih orodij ................................................................................ 62

Tabela 10: Meritve aktivnosti ............................................................................................. 71

Tabela 11: Porazdelitev aktivnosti (prirejeno po [55]) ....................................................... 72

Tabela 12: Primerjava metrik kode (prirejeno po [55]) ...................................................... 75

Tabela 13: Primerjava metrik testov (prirejeno po [55]) ..................................................... 75

Tabela 14: Ostale metrike praktičnega dela ........................................................................ 76

9.3 Naslov študenta

Ime in priimek: Bernard Atelšek

Naslov: Aškerčeva 5 b

Pošta: 3325 Šoštanj

Tel. študenta: +386 31 851 307

E-pošta študenta: [email protected]

Page 99: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 87

9.4 Kratek življenjepis

Rojen: 10. 5. 1984 v Celju

Šolanje: 1991–1999 Osnovna šola Karla Destovnika Kajuha, Topolšica, Šoštanj

1999–2003 Poklicna in tehniška elektro in računalniška šola, Velenje

2003–2011 Fakulteta za elektrotehniko, računalništvo in informatiko, Maribor

Page 100: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 88

Page 101: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 89

Page 102: TESTNO VODEN RAZVOJ PROGRAMSKIH REŠITEV · III ZAHVALA Zahvaljujem se mentorju – red. prof. dr. Marjanu Heričku za pomoč in vodenje pri pisanju diplomskega dela. Posebna zahvala

Testno voden razvoj programskih rešitev Stran 90