Ohjelmoinnin peruskurssien laaja oppimäärä Luento 19: Testaus, UML, suunnittelumalleja Riku Saikkonen (merkityt ei-laajan kurssin kalvot: Otto Seppälä) 17. 3. 2011
Sisältö 1 Ohjelmien automaattinen testaus 2 Yksikkötestaus 3 Yksikkötestaustyökalu JUnit 4 UML-luokkakaaviot 5 Vielä muutama suunnittelumalli
Testaus "Program testing can be used to show the presence of bugs, but never to show their absence!" Edsger Dijkstra 00:23
Testaus Testaus vertaa ohjelman toimintaa sen oletettuun toimintaan (spesifikaatio) Poikkeamaa spesifikaatiosta kutsutaan virheeksi Spesifikaatio ei aina ole täydellinen Speksin tulkinnat on hyvä merkitä testin yhteyteen Testaus pyrkii osoittamaan virheiden olemassaolon Mutta ei voi todistaa virheettömyyttä Paitsi jos kaikki mahdolliset tilat ja syötteet käydään läpi jolloin kyseessä onkin jo oikeastaan mallintarkistus Hyvä testi pystyy näyttämään aiemmin tuntemattoman virheen olemassaolon Testaus pyrkii testaamaan ohjelmaa tai sen osaa tietoisesti sekä 00:23 perustapauksilla, että spesifikaation rajoilla ja erikoistapauksissa
Testaus Testijoukon tulisi olla kattava Testaus ei ole helppoa Testattavuus riippuu paljon ohjelman rakenteesta, ts. kuinka helppoa ohjelman osat on irroittaa toisistaan testiä varten. Olion sisäinen tila riippuu suoritushistoriasta, yksittäistä operaatiota testaava testi voi mennä läpi, mutta useamman operaation mittainen epäonnistua. Tietyn virheen tuottavan suoritushistorian luominen voi olla hyvinkin hankalaa Esim ohjelmaa käytettäessä havaittujen bugien toistaminen. Rinnakkaisohjelmoinnissa suoritushistorian rooli korostuu vielä enemmän, virheet toistuvat satunnaisesti ja mahdollisesti hyvin harvoin. 00:23
Helpompaa testausta Määrittele luokkien väliset rajapinnat yksinkertaisiksi ja selkeiksi Monimutkaiseen rajapintaan on vaikea kirjoittaa tynkäluokkia (tynkä on jotain oikeaa luokkaa simuloiva pikkuluokka) Enkapsulaatio Mitä vähemmän olion sisäinen tila riippuu muusta maailmasta, sitä helpompaa sitä on testata Lisäksi virheitäkin tulee todennäköisesti vähemmän Toisaalta private-metodit täytyy testata epäsuorasti Vai täytyykö? Metodien ja luokkien jako pienempiin, hallittavampiin osiin Pieniä luokkia on helpompi testata 00:23 Kaikki mainitut ovat muutenkin hyvän koodin tunnusmerkkejä
Tynkäluokka Tynkiä voi käyttää testatessa ja uutta koodia kehittäessä Allaolevassa esimerkissä tyngän avulla simuloidaan puuttuvaa tietokantaluokkaa luokalla joka aina löytää haluamansa. Hyöty: Kaiken koodin ei tarvitse olla kerralla valmiina vaan kehitettävää koodia pääsee ajamaan jo alkuvaiheessa. Hyöty: Tynkätietokanta voidaan pakottaa toimimaan oikein. Esimerkin koodi tekee aika karkean yksinkertaistuksen Mieti millaisessa tilanteessa tätä koodia tarvitseva osuus toimisi väärin? public interface CustomerDatabase { public Customer getcustomerbyname(string name); } public class CustomerDatabaseStub implements CustomerDatabase { } public Customer getcustomerbyname(string name) { // ei haeta oikeasti kannasta vaan luodaan lennossa return new Customer(name); } 00:23
Testaus ja Extreme Programming Test-first toteutusjärjestys Ohjelmointi aloitetaan testien suunnittelulla ja toteuttamisella Kun uusia ominaisuuksia toteutetaan, ne voidaan heti testata Jos ohjelma toimii väärin, kirjoitetaan ensin testi joka osoittaa virheen olemassaolon ja vasta sitten ryhdytään korjaamaan virhettä 00:23
Formaali verifiointi Ohjelman virheettömyyttä ei voi todistaa testaamalla Jos ohjelman on välttämätöntä olla virheetön, sen toiminnallisuus todistetaan formaalilla verifioinnilla Formaali verifiointi Formaali verifiointi pyrkii todistamaan ohjelman oikeellisuuden, joko : Tutkimalla kaikki ohjelman tilat : mallintarkistus Matemaattisella todistuksella : invariantit, temporaalilogiikka,jne. Käytännössä tämä on raskasta ja tehtävissä vain rajallisen kokoisille ohjelmille Esim: tiedonsiirtoprotokollat, hardware Ei käsitellä tällä kurssilla 00:23
Testauksen tasoja Järjestelmätestaus (System testing) (suoritetaan viimeiseksi) Koko järjestelmän testaaminen järjestelmän spesifikaatiota vastaan Integraatiotestaus (Integration testing) (koodin osia yhteen liitettäessä) Ohjelman osien testaaminen yhdessä Erityisesti ohjelman osien välinen tiedonvaihto Yksikkötestaus (Unit testing) (tästä yleensä aloitetaan) Yksikkötestauksessa ohjelmasta testataan pientä osaa, usein yksittäistä metodia tai luokkaa Verrataan tekniseen spesifikaatioon Testaus pyritään yleensä suorittamaan riippumattomasti muista 00:23 ohjelman osista
Sisältö 1 Ohjelmien automaattinen testaus 2 Yksikkötestaus 3 Yksikkötestaustyökalu JUnit 4 UML-luokkakaaviot 5 Vielä muutama suunnittelumalli
Yksikkötestaus Yksikkötestaus (Unit testing) Yksikkötestauksessa ohjelmasta testataan pientä osaa Verrataan tekniseen spesifikaatioon Testaus pyritään yleensä suorittamaan riippumattomasti Monesti joudutaan toteuttamaan ns. Testipeti Simuloi muita ohjelman osia Sisältää usein tynkäluokkia, oikeiden luokkien sijaan Helpottaa testausta Muut luokat saadaan toimimaan tarkalleen speksin mukaan ennenkuin niitä on olemassakaan Erikoistapaukset on monesti helpompi generoida näin, kuin käyttämällä muita luokkia normaalisti Muista luokista voidaan kaivaa tietoja jotka eivät muuten olisi saatavilla 00:23
Yksikkötesti Yksikkötestin kuvaus sisältää Sanallisen kuvauksen siitä mitä testi testaa Ohjelmalle testissä annettavat syötteet, tai miten ne muodostetaan Esim tiettyjen metodien kutsuminen tietyssä järjestyksessä, esim: Add(0), Add(1), Delete(0) Ohjelman (olioiden) tila ennen testiä Odotetut tulosteet (ja olioiden tila) joihin verrataan Yksikkötesti Yrittää varmistaa että jokin koodin osa toimii niin kuin kehittäjä luulee sen toimivan. 00:23
Testausvinkkejä Testaa aina: Sallituilla äärirajoilla Esim. Poista listasta alkio kun siellä on vain yksi alkio. Laittomilla äärirajoilla Esim. Katso tuleeko koodilta speksin mukainen poikkeus Normaaliarvoilla Esim. Hae listasta jossa on kymmenen alkiota alkiota joka ei ole siellä ja katso että paluuarvo on false. Jos käytät satunnaisuutta, alusta satunnaislukugeneraattori itse vakioarvolla Virhetilanteet voi tällöin toistaa ja debugata Tai tallenna käyttämäsi siemenluku, jotta voit toistaa testit 00:23
Black-box- ja white-box-testaus toinen (testauksen tasoista riippumaton) tapa luokitella testejä black-box-testit tehdään testattavan asian speksin (rajapinnan) perusteella mahdollisesti jo ennen koodin kirjoittamista testattava asia on musta laatikko, jonka sisälle ei haluta katsoa white-box-testit tehdään koodin perusteella esim. yritetään kattaa testeillä kaikki koodin rivit tai eri lailla käyttäytyvät tilat, joissa olio voi olla tai tilakoneen tapaan käyttäytyvästä ohjelmasta kaikki tilasiirtymät eri tilojen välillä
Ekvivalenssiluokat ja raja-arvoanalyysi black- ja white-box-testauksen avuksi on muutamia puoliformaaleja menetelmiä eräs tapa tehdä black-box-testejä (nimeltään equivalence partitioning / boundary value analysis): etsi syötteen osien ekvivalenssiluokat: arvoalueet, joilla testattavan osan pitäisi käyttäytyä samalla lailla etsi ekvivalenssiluokkien rajat (reuna-arvot) tee testisyötteet a) jostain ekvivalenssiluokan keskeltä, ja b) jokaisen reuna-arvon ympäriltä testaa vain yhtä arvoa kerrallaan (älä yhdistele eri testejä) esim. itseisarvon x laskeva funktio abs(x) ekvivalenssiluokat: x < 0, x = 0, x > 0 raja-arvot: x = 1, x = 0, x = 1 testataan esim. arvoja 100, 1, 0, 1, 100 ehkä myös 2, 2 (reuna-arvojen vierestä) ja pienin ja isoin (toisiksi pienin ja toisiksi isoin) x:n arvo, jos x on esim. 32-bittinen luku
Testikattavuuden mittoja Testeille on olemassa joitakin kattavuusmittoja, esimerkkejä kontrollivuon kattavuusmitoista: Rivikattavuus, lausekattavuus (WebCAT) tutkivat kuinka suuri osa riveistä suoritetaan vähintään kerran testauksen aikana Ehtokattavuus (WebCAT) Ehtolauseissa kaikkien ehtolauseiden ehtojen tulee saada kaikki arvonsa Polkukattavuus Ohjelman suoritus haarautuu ehtolauseissa. Polkukattavuus pyrkii mahdollisimman monen eri polun suorittamiseen. 00:23 Jopa täydellinen rivikattavuus voi olla vaikea saavuttaa
Regressiotestaus Regressiotestaus tarkistaa että järjestelmään tehdyt muutokset eivät ole rikkoneet aiempaa toiminnallisuutta Jos yksikkötestit on rakennettu jollakin automatisoidulla testaustyökalulla, on regressiotestaus hoidettavissa kivuttomasti Ajetaan kaikki testit uudestaan muutoksen jälkeen. 00:23
Sisältö 1 Ohjelmien automaattinen testaus 2 Yksikkötestaus 3 Yksikkötestaustyökalu JUnit 4 UML-luokkakaaviot 5 Vielä muutama suunnittelumalli
JUnit Junit on helppokäyttöinen yksikkötestaustyökalu hyvä tuki eri IDE:issä (mm. Eclipse), standardi Testit kirjoitetaan omaksi luokakseen, sisältäen : Koodin joka pystyttää testitilanteen Esim luo tarvittavat oliot, avaa tiedostot jne. @Before public void doallnecessarythings() Koodin joka ajaa testit ja todentaa tulokset @Test public void issavingfilesworking() Koodin joka purkaa testitilanteen : sulkee tiedostot... @After public void cleanup() 00:23
JUnit Perustesti (JUnit versio 4) Ota JUnit-kirjaston nimistö käyttöön importeilla Päätä luokkasi nimi sanaan Test (Webcat) Testimetodien eteen annotaatio @Test Testattavat asiat tarkistetaan assertnnn komennoilla import org.junit.test; import static org.junit.assert.assertequals; public class BasicTest { } @Test public void addzero() { MyInteger value = new MyInteger(123); MyInteger zero = new MyInteger(0); } MyInteger expectedresult = new MyInteger(123); MyInteger result = value.add(zero); assertequals(expectedresult, result); 00:23
JUnit Perustesti (JUnit versio 3) Ota JUnit-kirjaston nimistö käyttöön importilla Periytä luokkasi luokasta TestCase Testimetodien nimet alkavat aina test... Testattavat asiat tarkistetaan assertnnn komennoilla import junit.framework.*; public class BasicTest extends TestCase{ } public void testaddzero(){ MyInteger value = new MyInteger(123); MyInteger zero = new MyInteger(0); } MyInteger expectedresult = new MyInteger(123); MyInteger result = value.add(zero); assertequals(expectedresult, result); 00:23
@Test, @Before, @After @Test-annotaatiolla merkitään metodit jotka sisältävät testejä. JUnit suorittaa ne kaikki. Vaikkapa metodi joka kutsuu binäärisen hakupuun lisäysmetodia ja sitten hakee sen puusta contains-metodilla. Assert-metodilla vaaditaan että contains:in tulee palauttaa true. @Before-annotaatiolla merkitään metodit jotka suoritetaan ennen jokaista testiä. Kaikille testeille yhteisten muuttujien alustaminen, etteivät testit vaikuta toisiinsa jne... @After-annotaatiolla merkitään metodit jotka suoritetaan jokaisen testin jälkeen. Esim @Beforessa avattujen tiedostojen sulkeminen tms. 00:23
JUnit - Assert assertnnn-metodeilla jokin ehto jonka tulee olla totta. Jos ehto ei ole totta, testin kohta ei mene läpi. Assert-luokassa on paljon erilaisia assert-metodeja asserttrue(string message, boolean condition) Parametrin pitää olla true assertfalse(string message, boolean condition) Parametrin pitää olla false assertequals(string message, Object haluttu, Object todellinen) Parametrien pitää olla samat assertnull, assertnotnull jne.. käytännössä kaikki muut variaatiot voi kuitenkin rakentaa käyttämällä metodia asserttrue Koko lista löytyy API:sta http://junit.sourceforge.net/javadoc/org/junit/assert.html 00:23
Entä Scalassa? JUnit toimii suoraan myös Scalassa lisäksi Scalalle itselleen on tehty mm. ScalaTest JUnitin tyyppinen, mutta käyttää esim. funktioargumentteja hyväkseen sillä testikoodista saa vähän lyhyempää ja projekteissa on itse tehty pieni testaustyökalu yksinkertainen testaustyökalu on helppo tehdä... useimpiin ohjelmointikieliin on tehty vastaava yksikkötestaustyökalu (tai useita)
Sisältö 1 Ohjelmien automaattinen testaus 2 Yksikkötestaus 3 Yksikkötestaustyökalu JUnit 4 UML-luokkakaaviot 5 Vielä muutama suunnittelumalli
!"#! $%&'(')*+%,-./%0'11&+./2332&&45++5/6'&7--./ 135+63)1895&/+9&5533/.9:/!"#(%0'11-1--6&'.-: " ;3&./09+&./5+)733.1&./+9&,:/900..&5+%5-+99-</,&%%-&9&-/%0'11&-/ ')*+%,--./'./5-41'&509/%--5&-</+..+./')*+%,-1''7&./ 1&4*'&55-,&95-: "!"#</!.&=&+7/"'7+%&.>/#-.>0->+</'./1'1'+%,-/+4&%-&9&-/ ')*+%,&95'*+./50'55-,&924'9+99+&)&./%&&55?6&3/,+41&.535-2'*-:/ @3,3/%0'11-1--6&'.'5--5&'/'./?19&/?%+&9&,,&./13?5+5?&953/!"#A./'9&95-: " B'1+&%+/2&&4533/%0'11-1--6&'/5+1.&9++./900..&5+%,--9& #B0./'%+5/2&&453.?5/1--6&'.</2')7&/10&.1-/*'51&./')*+%,-9&/ ',&.-&9007+5/5'&,&6-5A/B0&.1-/%0'11&+./,+5'7&5/105906-5/5'&9&--./ 10./*'5-&./',&.-&90055-/13?5+533.:/$.1'/1--6&'99-/1-&11&/5-46&550C "#$%&!
!"#(,-%%&..091&+%&!!"# "!"#(1&+%&/%0'5&&./DE(%060./20'%&63%&993/1'46--,--./*'011'/ +4&%-&9&-/,-%%&..091&+%&3</*'&%%-/'%&/2-%*'./?)5+&953/,055-/,?89/ 2-%*'./2&110/+4'*-: " "-%%&..091&+%+./-60%%-/'./)+%22'/900..&5+%%-/9004+,2&-/ *34*+95+%,&3</+9&5533/5&+5'-/.'2+-95&/*-/2&+.+993/5&%-99-</9+%&5533/ -9&'&5-/,0&%%+1&./10&./')*+%,'&*&%%+/*.+:/*.+: " F-4)--./106-./,-%%&..091&+%+953/9--/1'1+&%+,-%%-/9&53/&59+! *'5+./2&5+,,&553/20)+&55-::: " @0509505--./%0'11-7&->4-,,&&.! "#$%&
!"#$% ''!.%/(0+'1%%/('2$(3(%0(4 ''!.%/(0+'1%%/('($(3(%0(4 ''!.%/(0+'1%%/('/()+53(%0(4 ''!.%/(0+'1%%/(',%6+(3(%0(4 '' ''!"#$%&'*+$%,71%%/('2$8999' ''''0:%)92$(3(%0(';'2$4 ''''0:%)9($(3(%0(';'($4 ''''0:%)9/()+53(%0(';'/$4 ''''0:%)9,%6+(3(%0(';',$4 ''<!"#/%0'11-7&->4-,,&!"#$%&'&$())'*+$%,- ''!"#$%&'%50'$()6+=%50(>$(7?- ''''9999 ''< ''!"#$%&'/,%@'()+0(1(.%7A,$,.'&?- ''''9999! "#$%&
!"#$% &#'()"*$+,'-#'./010$+, &'(",'2'3$.415%#%3/16%$7 ''!.%/(0+'1%%/('2$(3(%0(4 ''!.%/(0+'1%%/('($(3(%0(4 ''!.%/(0+'1%%/('/()+53(%0(4 ''!.%/(0+'1%%/(',%6+(3(%0(4 '' ''!"#$%&'*+$%,71%%/('2$8999' ''''0:%)92$(3(%0(';'2$4 ''''0:%)9($(3(%0(';'($4 ''''0:%)9/()+53(%0(';'/$4 ''''0:%)9,%6+(3(%0(';',$4 ''<!"#/%0'11-7&->4-,,&!"#$%&'&$())'*+$%,- ''!"#$%&'%50'$()6+=%50(>$(7?- ''''9999 ''< ''!"#$%&'/,%@'()+0(1(.%7A,$,.'&?- ''''9999! "#$%&
89#':'$,' 8'#':'$,' 86'("+:'$,' 8%$)"':'$,'!"#$% 12$$6' 12$$6' 12$$6' 12$$6' &#'()"*$+,'-#'./010$+, &'(",'2'3$.415%#%3/16%$7 ''!.%/(0+'1%%/('2$(3(%0(4 ''!.%/(0+'1%%/('($(3(%0(4 ''!.%/(0+'1%%/('/()+53(%0(4 ''!.%/(0+'1%%/(',%6+(3(%0(4 '' ''!"#$%&'*+$%,71%%/('2$8999' ''''0:%)92$(3(%0(';'2$4 ''''0:%)9($(3(%0(';'($4 ''''0:%)9/()+53(%0(';'/$4 ''''0:%)9,%6+(3(%0(';',$4 ''<!"#/%0'11-7&->4-,,&!"#$%&'&$())'*+$%,- ''!"#$%&'%50'$()6+=%50(>$(7?- ''''9999 ''< ''!"#$%&'/,%@'()+0(1(.%7A,$,.'&?- ''''9999! "#$%&
89#':'$,' 8'#':'$,' 86'("+:'$,' 8%$)"':'$,'!"#$% 12$$6' 12$$6' 12$$6' 12$$6' &#'()"*$+,'-#'./010$+, &'(",'2'3$.415%#%3/16%$7 +;)9699(<;;3"", &00=>?#$4 8000=3$6'," @00=3%,"4,"7 00007"A'>#, ''!.%/(0+'1%%/('2$(3(%0(4 ''!.%/(0+'1%%/('($(3(%0(4 ''!.%/(0+'1%%/('/()+53(%0(4 ''!.%/(0+'1%%/(',%6+(3(%0(4 '' ''!"#$%&'*+$%,71%%/('2$8999' ''''0:%)92$(3(%0(';'2$4 ''''0:%)9($(3(%0(';'($4 ''''0:%)9/()+53(%0(';'/$4 ''''0:%)9,%6+(3(%0(';',$4 ''<!"#/%0'11-7&->4-,,&!"#$%&'&$())'*+$%,- ''!"#$%&'%50'$()6+=%50(>$(7?- ''''9999 <>>,,>B'+C0='3'<",3$+0,'$0 ''< ='#>>'36%+0,99==$0 )')(%$(=$(,""+0B;#)""+ ''!"#$%&'/,%@'()+0(1(.%7A,$,.'&?- ''''9999! "#$%&
G99'9&--5&'!"#$% 2$$6'!"#$%&'&$())'*+$%,- ''!.%/(0+'1%%/('2$(3(%0(4 ''!.%/(0+'1%%/('($(3(%0(4 ''!.%/(0+'1%%/('/()+53(%0(4 ''!.%/(0+'1%%/(',%6+(3(%0(4 '' ''!"#$%&'*+$%,71%%/('2$8'1%%/('($8'1%%/('/$8'1%%/(',$?- ''''0:%)92$(3(%0(';'2$4 ''''0:%)9($(3(%0(';'($4 ''''0:%)9/()+53(%0(';'/$4 ''''0:%)9,%6+(3(%0(';',$4 ''< <! "#$%&
G99'9&--5&' "@@& '!"#$% 2$$6'!"#$%&'&$())'*+$%,- ''!.%/(0+'1%%/('2$(3(%0(4 ''!.%/(0+'1%%/('($(3(%0(4 ''!.%/(0+'1%%/('/()+53(%0(4 ''!.%/(0+'1%%/(',%6+(3(%0(4 %! +4314**225!19*:2!1-* ''!"#$%&'*+$%,71%%/('2$8'1%%/('($8'1%%/('/$8'1%%/(',$?-?@@A! 59**46+4!B,,+225!1-* ''''0:%)92$(3(%0(';'2$4 ''''0:%)9($(3(%0(';'($4 ''''0:%)9/()+53(%0(';'/$4 &@@C! C B><,5+>>5!1416,!1-* D4-44B4*,5+4,525!:>>3> ''''0:%)9,%6+(3(%0(';',$4 ''< E6,:231,66>::2!/<+225!52*,FF5!1))*))!4,54!+4645! '!B,,B44G!:)++4!/16,!B,,B4!B9,!1))*)4!;919!/<+225!+4,! 14<+225!52*,FF5 <! ()*+,-*,.,+/!012334554,6))67 823+99!1),514!:95225!+9,625!*)9145!9*,995! ;91,5!*)9145!9*,9!95!/<+2/=266> "#$%&
G99'9&--5&' 32)54+ '!"#$% 2$$6'!"#$%&'&$())'*+$%,- ''!.%/(0+'1%%/('2$(3(%0(4 ''!.%/(0+'1%%/('($(3(%0(4 ''!.%/(0+'1%%/('/()+53(%0(4 ''!.%/(0+'1%%/(',%6+(3(%0(4 D,,B45!:231,+/6!52*,F**2!95G!2++>!62! ''!"#$%&'*+$%,71%%/('2$8'1%%/('($8'1%%/('/$8'1%%/(',$?- +9,:,,!52*,F5!32)5454@ ''''0:%)92$(3(%0(';'2$4 ''''0:%)9($(3(%0(';'($4 ''''0:%)9/()+53(%0(';'/$4 ''''0:%)9,%6+(3(%0(';',$4 ''< <! H99*, 8431246+,$!123+99!:,1>!+>:>5! 6)<+225!->>5!:231,+/6!95!+9,62**2! ->>**2 "#$%&
;-6&>-H&%&5? 32)54+ '!"#$% 2$$6'!"#$%&'&$())'*+$%,- ''!.%/(0+'1%%/('2$(3(%0(4 ''!.%/(0+'1%%/('($(3(%0(4 ''!.%/(0+'1%%/('/()+53(%0(4 ''!.%/(0+'1%%/(',%6+(3(%0(4 D,,B45!125+,66>!2,! ''!"#$%&'*+$%,71%%/('2$8'1%%/('($8'1%%/('/$8'1%%/(',$?- ''''0:%)92$(3(%0(';'2$4 B>*++>:>++>!9*2!B,,++4)16,4! ''''0:%)9($(3(%0(';'($4 I2*,FJ*)9145!9*,9,<,5 ''''0:%)9/()+53(%0(';'/$4 ''''0:%)9,%6+(3(%0(';',$4 ''< <! I2*,F5!125+,66>!95!;9**4,5! +4B4**4!+4**2664!B,,++4)16,4! D,,B4J9*,9,<,5 "#$%&
89:-96,+,9!;4!4NN32N44+,9!1)B44B4+G!2++>!;91,5!1996+))!-,252::,6+>!9646,6+4@!O96! L->>9*,995L!19<=,6+2+445!9-2344+,9,+4G!52!19<=,6+)B4+!;9**4,5!+4B9,5!:/F6!625! 9646,,5@!89:-96,+,9!95!4NN32N44+,9+4!;/312:-,!L1996+2L B',2'9&5&' 32)54+ '!"#$% 2$$6' G>>4+>--5&' KI2*,F!1996+))!B,,B9,6+4G ;96!52*,F!-9,6+2+445!B,,B4+1,5!<>B,>B>+L *'3$ & D)($#% KM43,!1996+))!/16,*F,6+>G ;96!-43,!-)314)+))G!/16,*F+!6>,*/B>+!6,*+,L! "#$%&
I&&2206009 32)54+ '!"#$% 2$$6' &#'()"*$+,'-#'./010$+, &'(",'2'3$.415%#%3/16%$7 H,,--)B))6 8431246+,$!P)9114!1>/++>>!+9,625!*)9145! 9*,9,+4!+4,!5,,=25!:2+9=2,+4 026,:@!-434:2+32,547!:)++4!2,!6>,*/+>! B,,++4)16,4!625!9*,9,<,5 5%#%3! "#$%&
F+4&.53 E>6$% M23,5+> P)9114!-23,,!+9,625!*)9145!9:,54,6))=2+G!;4! 625!9*,995!B9,=445!B,,+4+4!/*>*)9145!+//--,625! :))++);45!14)++4@! 32)54+ '!"#$% 2$$6'! "#$%&
J9&,+411& & B45<2::4+ FG<$+"+ *4-62+ C H21)36,,B,525!46696,44+,9 P)9145!9*,9+!B9,B4+!+,2+251,5!B,,+4+4!+9,6,,5!64:45*)9145! 9*,9,<,5@!E6,:!Q<:,525J*)914664!B9,!9**4!B,,++4)6!:),<,5! Q<:,525J*)9145!9*,9,<,5@!! "#$%&
J9&,+411& *'+))$ (95+4!46696,44+,9+4 84<=25!*)9145!9*,9,=25!B>*,**>!644!9**4!:/F6!)624:-,4! 46696,44+,9,+4G!:)++4!+>**F,5!14554++44!62*,++>>!:,+>!23,! 6)<+22+!1)B44B4+@! " C -($')'( " 9:,6+4;4 C *'+))$,$#$ C! 1>/++F9,12)6 C "#$%&
I-*-2&..-./53?553,&.+. RR,5+23S4.2TT E>()$ -B",,'6' H4;4-,5545!+>/++>:,525 O96!;91,5!*)9114!6,6>*+>>!34;4-,5545!B44+,:45! *,6+45!:2+9=,+G!62!+>/++>>!34;4-,5545@!V>+>! 6)<=2++4!1)B4+445!5)9*2**4!;9**4!95!95++9!1>31,! ;4!14+19B,,B46+4!1996+)B4!B436, ->,% H)%%,,"3$! "#$%&
GH954-15&/%0'11- RR4W6+34.+TT I9J+,")$B; XW6+341+,!*)9114 XW6+341+,!*)9114!95!+4B4**,625!*)9145!;4! 34;4-,5545!B>*,:)9+9@!Y2!95!*)9114G!;914! +9+2)++44!;9,+41,5!:2+9=2,+4G!:)++4!9645! :2+9=2,6+4!19<=4**4!62!4,5946+445!+9+244!2++>! 52!+>/+//!;951)5!:))5!*)9145!+9+2)++44@ XW6+341+,!*)9114!95!L-)9*,B4*:,6L!*)9114G!;914! 45+44!B4-44+!1>=2+!-))++)B,25!:2+9=,25! +9+2)+)162**2@ E%))$ *%#$$($! "#$%&
Sisältö 1 Ohjelmien automaattinen testaus 2 Yksikkötestaus 3 Yksikkötestaustyökalu JUnit 4 UML-luokkakaaviot 5 Vielä muutama suunnittelumalli
Iterator Monesti jonkin tietorakenteen kaikki alkiot tulisi käydä läpi (vaikkapa tallentaa tiedostoon) Tietoa voi kuitenkin olla monenlaisissa rakenteissa: puita, listoja, verkkoja jne. Iterator-rajapinta mahdollistaa rakenteen läpikäynnin ilman että sitä käyttävän tarvitsee tuntea rakenne Koska Java API:ssa on valmis rajapinta tälle, kannattaa tätä mallia käyttävän aina käyttää mainittua rajapintaa. 10:03
Proxy Proxy toimii jonkin toisen olion sijaisena ja säätelee olioon kohdistuvaa käyttöä. Kun jotain proxy-olion metodia kutsutaan, se yleensä kutsuu todellisen olion metodia Tyypillisesti sekä proxy-olio että oikea olio täyttävät saman rajapinnan, joten käyttävä luokka ei huomaa eroa Käyttävä Luokka <<interface>> Kohde +operaatio() todkohde.operaatio() TodellinenKohde +operaatio() todkohde Proxy +operaatio() 10:03
Proxy Käyttötapoja : Proxyn kauttaa voidaan käyttää olioita jotka sijaitsevat aivan muualla (levyllä, verkossa jne.) (remote proxy) Lazy initialization: Proxyn suojaama olio voidaan alustaa vasta tarvittaessa. (virtual proxy) Proxyn avulla saman luokan eri olioille voidaan antaa erilaiset näkyvyydet. (protection proxy) Proxy mahdollistaa sen suojaaman olion vaihtamisen ilman päivityksiä siihen osoittavissa olioissa. Tietorakenne ei voi tietää kuka siihen viittaa, joten esimerkiksi rakenteen tyhjentyminen ja täyttyminen uudestaan voisi ilman proxya olla ongelma Asetusten vaihtaminen kesken ohjelman ajon jne... 10:03
Command Joskus halutaan suorittaa jokin toiminto tietämättä ennalta mitään kutsuttavasta metodista tai oliosta jonka metodia kutsutaan. Command-mallin idea on kapsuloida metodikutsu olion sisään. Komento-olioita vaihtamalla voidaan vaihdella toiminnallisuutta Oliot voivat Command-olioiden kautta kutsua metodeita, jotka voidaan toteuttaa niistä täysin irrallisina. Komentoa Kohde Käyttävä Luokka +operaatio() komennonkohde <<interface>> Komento +suorita() TodellinenKomento +suorita() komennonkohde.operaatio() 10:03
Command Command-olioita voidaan puskuroida, tallentaa jne. Voidaan tehdä makroja, tai suorittaa vasta kun mahdollista Komennoista voidaan joissain tilanteissa tehdä peruutettavia. Suorita()-metodi tallentaa tällöin olennaiset tiedot jotta peruutuksen voi tehdä. Lisätään rajapintaan metodi peruuta() Laitetaan Komento-oliot talteen niiden suorituksen jälkeen PoistuKomento Ohjelma Komentoa Käyttävä Luokka <<interface>> Komento +suorita() +suorita() KopiointiKomento +suorita() +lopeta() Leikepöytä +kopioivalinta() 10:03