Praktikum 5. Automaattestid, debuggeri kasutamine.
ÜLESANDED KLASSIS
Ülesanne 1. Automaattestid ja JUnit.
Kasutame alusena lihtsat näidisprojekti: lab5-testing-demoapp.zip.
Projektis sisalduvad kolm Java mudeliklassi (ükski neist ei sisalda meetodit main
ja seega pole tegemist iseseisvalt käivitatava rakendusega). Koosneb lihtsast mudelist, mille klassid on järgmised:
SaleItem
- Erinevad kaubaartiklid. Igal kaubaartiklil on nimi ja tükihind.Bill
- Üks arve. Sisaldab mitmeid ridu. Oskab arvutada enda summaarse maksumuse.BillRow
- Üks rida arvel. Sisaldab viidet konkreetsele kaubaartiklile ning viidet selle kaubaartikli müüdud kogusele antud arvel. Võib sisaldada ka allahindlusprotsenti konkreetse ostu puhul konkreetse kauba jaoks (vaikimisi on allahindlusprotsendiks 0%). Oskab arvutada iseenda väärtuse.
Rakenduse "päris" kood asub kataloogis \src\java
. Lisaks on rakendusega kaasas JUnit raamistiku abil realiseeritud automaatsed ühiktestid, mille kood asub kataloogis \src\test
. Teste saab käivitada kas käsurealt käsuga ant test
või läbi Eclipse'i "jooksutades projekti JUnit testidena" (Ctrl+F11 või Alt+Shift+X,T).
Ülesanne: Kummaski testklassis sisaldub mitmeid tühje meetodeid, mis peaksid testima erinevaid mudeli omadusi, kuid on hetkel realisatsioonita. Realiseerida vastavad meetodid!
ÜLESANDED KODUS
Ülesanne 1. Kassasüsteemi katmine automaattestidega.
Lisada kassasüsteemile JUnit. Selleks tuleb lisada vastav jar-fail junit-4.7.jar, tekitada testide hoidmiseks projekti täiendav lähtekoodi kaust ning lisada Ant skripti target testide käivitamiseks. Konfigureerimisel kasutage näidisena näidisrakendust klassis tehtud ülesandest.
Igas rakenduses (ja nii ka SalesSystemis) on palju klasse, mida ühiktestidega katta on väga raske või vähemalt liiga raske et see oleks mõtekas (sõltuvad liiga paljudest välistest teenustestest jne). Rakenduse hea testitavus on muuhulgas ka märk heast disaininst.
SalesSystemi kasutatavas versioonis raskendavad ühiktestidega katmist väline andmebaas, Hibernate ning nende (liiga) tugev seotus rakenduse teiste osadega. Samuti on keerukas testida fat client kasutajaliidest. Küll aga saab SalesSystem'is kindlasti ühiktestidega katta andmemudeli klasse (Sale
jne) ning JTabel'eid abistavaid tabelite mudelite klasse (StockTableModel
jne).Kindlasti saate kirjutada vähemalt järgmised testid:
SaleTest
:testAddSoldItem()
testGetSumWithNoItems()
testGetSumWithOneItem()
testGetSumWithMultipleItems()
StockItemTest
testClone()
testGetColumn()
SoldItemTest
testGetSum()
testGetSumWithZeroQuantity()
StockTableModelTest
testValidateNameUniqueness()
testHasEnoughInStock()
testGetItemByIdWhenItemExists()
testGetItemByIdWhenThrowsException()
- Kirjutada ülalloetletud testid (testide nimed annavad mõnes kohas täiendavalt aimu erinevatest juhtumitest mida võiks testidega katta)! Kus võimalik, testida loetletud klassides teisigi meetodeid. Mitte kirjutada triviaalseid/mõttetuid teste (testid kas konstruktor tõepoolest loob uue objekti või kas getter tagastab sama väärtuse mis setteriga just seati)!!
- Leida tabeli mudeli klasside hulgast veel vähemalt paar ülal mainimata klassi, milles on meetodeid, mis ei ole päris triviaalsed ning mida saab ühiktestidega katta.
Ülesanne 2. Eclipse'i debuggeri kasutamine.
Debuggeriks nimetatakse üldiselt tarkvara, mis võimaldab programmi täitmist rida-realt jälgida, vajadusel see teatud punktides peatada või sellesse ka kõrvalt sekkuda (eesti keelseks vasteks on pakutud mõistet "silur", tegusõnana "siluma", kuid ei saa öelda et need terminid tunduksid eesti keeles loomulikud või oleksid rahuldavalt juurdunud). Debuggereid kasutatakse peamiselt programmide ja algoritmide töö analüüsimiseks ja nendest vigade (bugide -- siit ka nimi) leidmiseks.
Java Virtual Machine (JVM) võimaldab spetsiaalse protokolli abil enda külge ühenduda erinevatel debuggeritel. Antud praktikumis tutvume neist ilmselt kõige levinuma ehk Eclise IDE sisse ehitatud debuggeriga. JVM'i debugimis-võimaluste aktiveerimiseks tuleb see käivitada spetsiaalsete lipukestega. Nende lisamiseks teeme vastava muudatuse build.xml
-i. Pärast muudatust peaks run
targetis sisalduv <java>
task nägema välja umbes selline:
<java classname="ee.ut.math.tvt.salessystem.SalesSystem" classpathref="run.classpath" fork="yes" > <jvmarg value="-Xdebug" /> <jvmarg value="-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=1044" /> </java>
Käivitage pärast lippude lisamist kassasüsteem (kohe logi alguses peab nüüd näha olema logiteade Listening for transport dt_socket at address: 1044). Seejärel avage Eclipse, valige menüüst Run --> Debug configurations .., sealt Remote Java Application ning täitke aken ära õigete andmetega (host = locahost, port = 1044 või misiganes muu väärtus mis te build.xml
-i kirjutasite). Kui andmed sisestatud, vajutage nuppudele "Apply" ning "Debug" ja avage debugimise vaade (Window --> Open Perspective --> Debug). Kui kõik on hästi, näete avanevas vaates, et debugger on ühendatud JVM'i külge ning JVM'i sees jookseb ligikaudu 4 paralleelset threadi.
Töö debuggeriga algab tavaliselt kuhugi teid hetkel huvitavasse kohta breakpointi panekust ja jooksva programmi suunamisest selle breakpointini, kus debugger programmi täitmise peatab ning annab kontrolli programmi edasise täitmise üle kasutaja kätte. Tutvuge ja katsetage iseseisvalt debuggeri võimalustega ning vastake seejärel debuggerit kasutades järgnevatele küsimustele. Mõningatele neist saab vastata ka ilma debugger'it kasutamata - üritage siiski mõista, kuidas debugger''i kasutamine teid sellises olukorras aitab! Kasutage selle ülesande tegemisel algset koodi mis teile neljanda praktikumi ülesandega koos anti. Enda muudetud koodi kasutamine võib kohati anda pisut erinevaid vastuseid, mis loetakse pikema kontrollimiseta valedeks.
- Nimetage vähemalt üks meetod, kuhu method breakpointi panemine peatab programmi töö pärast Point-of-sale tabis New purchase nupu vajutamist.
- Nimetage meetod, kuhu method breakpointi panemine võimaldab programmi töö seisata kohe pärast Confirm nupu vajutamist ostu sooritamisel.
- Loetlege klassi
java.awt.Container
alamklasse, millel kutsutakse regulaarselt ülekaetud meetoditdoLayout()
kui te rakenduses ringi klikite (vihje: pange method breakpoint meetodileContainer#doLayout()
)) - Mitu korda kutsutakse pärast New purchase nupu vajutamist klassi
java.lang.String
ilma argumentideta konstruktorit (new String()
), enne kui joonistatakse valmis Choose client dialoogiaken ja lastakse kasutajal valida klient? - Mitu korda kutsutakse pärast New purchase nupu vajutamist klassi
javax.swing.JPanel
ilma argumentideta konstruktorit (new JPanel()
), enne kui joonistatakse valmis “Choose client” dialoogiaken ja lastakse kasutajal valida klient? - Minge Warehouse tabi, klikkige Add, täitke väljad mingite sobilike väärtustega. Lisage method breakpoint meetodile
StockTab#addItemOkPressed
. Klikkige kauba lisamise aknas Ok, mille peale jõutakse äsja lisatud breakpointi ja programmi täitmine peatub. Mis oli(d) viimane(/sed) kassasüsteemi enda meetod(id), läbi mille jõudis programm meetodisseaddItemOkPressed()
? - Peatage programmi täitmine samuti nagu eelmise küsimuse puhul. Peatatud threadi stackis kolmandaks meetodiks on meetod
actionPerformed
, mille argumendiks onActionEvent e
. Uurige seda objekti lähemalt. Mis one
isendiväljadeactionCommand
,consumed
jaisSystemGenerated
väärtusteks? - Peatage programmi täitmine samuti nagu eelmise küsimuse puhul, kusjuures sisestage eelnevalt vormile mõni mittevaliidne väärtus (näiteks hinna lahtrisse numbrite asemel tähed vms). Astuge debuggeriga mööda ridu alla kuni meetodikutseni
JOptionPane.showMessageDialog()
ning astuge debuggeriga sellesse meetodisse sisse, seejärel veelkord sisse ning veel üks kord sisse. Millise signatuuriga meetodisse jõudsite? - Millise nupu vajutamise peale kasutajaliideses kutsutakse konstruktorit
new java.util.Date()
? Mis on viimane kassasüsteemi enda klass millest see kutse sinna jõuab? - Millise tegevuse peale Point-of-sale tabil kutsutakse muu hulgas konstruktorit
new java.lang.Exception()
ja miks?
VIITED
- JUnit
- Eclipse debugger