Unit és integrációs tesztelés¶
JUnit¶
A JUnit 5 egységteszt keretrendszerrel fogunk megismerkedni.
Jellemzői¶
- Az xUnit család tagja, Java implementáció
- Reflection-t használ a tesztek futtatásához
- Könnyen készíthetők új tesztek
- Tesztcsoportok (suite) készíthetők
- Többféleképpen futtatható, azonnali eredményt ad
- Automatizálható és a keretrendszerekbe könnyen beépíthető
- Nem minden esetben használható!
- GUI tesztelés csak korlátozott módon (mock)
Assert metódusok¶
- Tesztelés közben ellenőrizzük, hogy a megfelelő eredményeket kapjuk-e
- Assert metódusokkal
- Ha nem megfelelő a kapott eredmény, a teszteset sikertelennek minősül (failed)
- Statikus metódusok (Java 5.0 – static import)
- assertFalse(BooleanSupplier condition), assertTrue(BooleanSupplier condition)
- assertEquals(expected, actual)
- az expected és actual paraméterek minden Java-ban támogatott típust felvehetnek, a metódusnak minden típusra létezik overloadolt változata
- assertIterableEquals(Iterable<?> expectedm Iterable<?> actual)
- assertNotEquals(Object unexpected, Object actual)
- assertArrayEquals(expected[], actual[])
- assertNull(Object actual), assertNotNull(Object actual)
- assertSame(Object expected, Object actual), assertNotSame(Object unexpected, Object actual)
- assertThrows(Class expectedType, Executable executable)
- Ez a metódus akkor assertál, amennyiben az executable az elvárt típusnak megfelelő kivételt dobja.
- assertTimeout(Duration timeout, Executable executable)
- fail()
- +vannak olyan verziók, ahol az első paraméter egy hibaüzenet
Tesztesetek definiálása¶
- A tesztosztály, tesztesetek publikusan legyenek
- A metódusokat annotációkkal látjuk el
- @Test
- a metódus egy teszteset (test case)
- opcionális paraméterek: expected, timeout
- ha lefut, a teszteset sikeresnek számít (nincs assert, exception)
- @ParameterizedTest
- Junit5-ben inkább használjuk ezt az annotációt, amennyiben paraméterezett tesztet futtatunk
- @ValueSource annotációval párban
Példa
1 2 3 4 5 6 7 8 9 10 |
|
Tesztek futtatása¶
- Statikusan: run() metódusokkal saját kódból
- Dinamikusan: TestRunner osztályok segítségével
- Konzolos TestRunner:
- java junit.textui.TestRunner
- Eclipse integráció:
- Jobb klikk a tesztosztályon: Run As | JUnit Test
- Legtöbb Eclipse verzióban már alapból benne van a JUnit plugin
Példa probléma¶
Hajókra tervezünk ütközéselkerülő rendszert. A rendszer alapja, hogy a saját hajó navigációs radarja érzékeli a másik hajó relatív helyzetét és relatív haladási irányát. A radarképeket polárkoordinátás rendszerben értelmezzük.
Radarképekre ld. az alábbi ábrát.
A hajó helyzetét egy x,y
koordinátapárban adjuk meg, ahol az y
tengely a hajó haladási irányával párhuzamos (a haladási irány felé pozitív), az x
tengely pedig arra merőleges (haladási iránytól jobbra pozitív), és a koordináta rendszer origójában van a saját hajó.
A másik hajó relatív haladási irányát fokban kapjuk meg (ez egy 0-359 közötti szám: 0 ha párhuzamosan azonos irányba; 90 ha merőlegesen balról jobbra; 180 ha párhuzamosan de ellentétes irányba; 270, ha merőlegesen jobbrül balra halad). A fenti ábrán ezt a szöget a sárgával jelölt terület mutatja.
Ezekből az adatokból a rendszer kiszámolja a két hajó útvonalának metszéspontját. Az ábrán az egyenes és az y tengely metszéspontja az.
Ezután a rendszer a saját hajó haladási sebességből és hosszából kiszámolja, hogy mikor (milyen időintervallumban) fog ezen a ponton áthaladni előtte-utána 3-3 hajóhossz ráhagyással. Ez azt jelenti, hogy a saját hajó eleje mikor közelíti meg 3 hajóhossznyira a metszéspontot, és a tatja mikor hagyja el legalább 3 hajóhosszal (viszonyítási pontnak a saját hajó geometriai közepét tekintve). Közben érzékeli a másik hajó folyamatosan sugárzott sebesség és hossz adatait, és azokkal is elvégzi a számolást. Ha a két hajó eltérő időintervallumban tartozkodik az adott helyen (az ábrán narancssárgával satírozott danger zónát), akkor nincs baj.
Ha viszont a két időtartamnak van közös része, azaz van olyan időszak, mikor mindkét hajó a danger zónában tartózkodna, akkor több lehetőség van:
- Ha a hajók haladási iránya legfeljebb 90 fokban tér el (azaz legfeljebb merőlegesen haladnak, de kicsit sem "egymással szemben"), akkor "a jobbról érkezőnek elsőbbsége van" alapon sebességcsökkentést javasol, vagy csak fokozott óvatosságra figyelmeztet.
- Ha viszont a két hajó kicsit is szemben halad egymással, akkor "a könnyebb hajó könnyebben menőverez" alapon javasol elkerülő manővert vagy fokozott óvatosságot. (A tömeg adatokat szintén folyamatosan sugározzák a hajók.)
A probléma, hogy az adatsugárzó rendszerek nem teljesen standardizáltak, ezért a sebesség, hossz és tömeg adatokat különféle hajók különféle mértékegységekben sugározhatják.
- Hosszmérték
- cm, m (100cm), km (1000m), in (2.54cm), ft (12in), yd (3ft), mile (1760yd), nm (1852m)
- Tömeg
- g, kg (1000g), t (1000kg), oz (28.34952g), lb (16oz)
- Idő
- s, m (60s), h (60m)
- Sebesség
- m/s, km/h, mi/h, knot (1 nm/h)
Egységtesztek¶
- Töltsd le az Eclipse projektet és csomagold ki
- Töltsd be Eclipse-be
- File -> Open Projects from file system
- File -> Import ... -> General -> Existing project into workspace
- Ship projektre jobb gombbal kattintás -> New -> Source folder -> Folder name:
test
test
folderre jobb katt -> New -> Package -> Name:scws
- Package-re jobb katt -> New -> JUnit test case -> New JUpiter test bepipálva
- Name -> UnitTests.java
- Which method subs would you like to create? - Mind a négyet ki kell pipálni.
- Írjuk be az alábbiakat:
Helyes Unit teszt (a Time
osztály as
függvényét teszteli.)
1 2 3 4 5 6 |
|
Helytelen (bukó) unit teszt (a Time
osztály as
függvényét teszteli.)
1 2 3 4 5 6 |
|
- Ship projektre jobb katt -> Run As -> JUnit Test
- Láthatjuk, hogy egy passed és egy failed tesztünk van.
Feladat: egységtesztek
Készíts egységteszteket JUnit segítségével.
Mi a teszt futtatásának eredménye?
Sikerült-e a tesztek segítségével valamilyen hibát felfedezni?
Egységteszt hiba
- Az
AbstractUnit
osztályint compareTo(T)
metódusa hibás
Integrációs tesztek¶
- Package-re jobb katt -> New -> JUnit test case -> New JUpiter test bepipálva
- Name -> IntegrationTests.java
- Which method subs would you like to create? - Mind a négyet ki kell pipálni.
- Írjuk be az alábbiakat, majd futtassuk le az előbb leírt módon
Helyes Integration test (hossz, idő és sebesség integrációja)
1 2 3 4 5 6 7 |
|
Feladat: integrációs tesztek
Készíts integrációs teszteket JUnit segítségével.
Mi a teszt futtatásának eredménye?
Sikerült-e a tesztek segítségével valamilyen hibát felfedezni?
Integrációs teszt hiba
- A
Length
osztály távolságból és sebességből időt számoló metódusa rosszul működik. - A
ShipCollisionWarningSystem
osztály rosszul számolja meg ez "előtt" és "mögött" fogalmát.
Rendszertesztek¶
Bár a JUnit (és a hasonló keretrendszerek) alapvetően egységtesztek megírására lettek tervezve, ez nem jelenti azt, hogy nem lehet magasabb szintű teszteket automatizálni a segítségükkel.
Az algoritmus
- Saját hajó (sebesség (V), hossz (L), tömeg (M), relatív irány 0 fok, relatív pozíció (0,0))
-
Másik hajó (sebesség (v), hossz (l), tömeg (m), irány (rd), relatív pozíció (dx,dy)) - ez lényegében a mi koordinátarendszerünkben mért pozíció.
-
Másik hajó irány és pozíció adataiból számoljuk ki, hogy, hogy keresztezi-e a saját hajó útvonalát?
- Ha a jobb oldalon (dx > 0) van és jobbra tart (0° ≤ rd ≤ 180°), vagy a bal oldalon (dx < 0) van és balra megy (180° ≤ rd ≤ 360°(=0°)), akkor nincs keresztezés és figyelmeztetés sem.
-
Számoljuk ki az útvonalak metszéspontját:
- A másik hajó v sebességét vx (nekünk merőleges) és vy (velünk párhuzamos) komponensekre kell felbontani:
Az ábrán is látható, hogy a phi szögből kell kiindulni, a vektor első koordinátája a vektor hossza szorozva az x tengellyel közbezárt szög koszinusza. Azonban a radar nem az x, hanem az y tengellyel bezárt szöget adja, ami az ábrán az rd. Ezért a phi= 90°-rd alapján: - vx = v * cos(90° - rd) - vy = v * sin(90° - rd) Ha a másik hajó iránya kicsit más, felénk közeledik, akkor a kövezkező ábrát tekintsük:
Itt az a trükk, hogy a phi előjele negatív! Ezért ugyanúgy kapjuk meg, mint az előző esetben phi= 90°-rd. Vagyis itt is - vx = v * cos(90° - rd) - vy = v * sin(90° - rd) Minden esetben az sebességkomponensek így számolódnak ebben a speciális koordinátarendszerben. - vx-ből és dx-ből kiszámolható, hogy a másik hajó t = - (dx / vx) (dx negatív, mert tőlünkl balra van ebben az esetben - ha nem, akkor nem találkozunk vele) idő múlva keresztezi a saját hajó útvonalát - vy-ból, dy-ból és t-ből kiszámolható, hogy a másik hajó az Y = dy + vy * t helyen keresztezi a saját hajó útvonalát (X=0, mivel mi definíció szerint az y tengelyen haladunk)
-
Mikor ér a két hajó az útvonalak kereszteződéséhez?
- A másik hajó az előbb kiszámolt t idő múlva
- Mi T = Y / V idő múlva (V a sebességünk)
- Ütközünk?
- A másik hajó dt = 3.5 * l / v idővel a keresztezés előtt lép be, és ennyivel ez után lép ki a danger zónából, vagyis [t-dt, t+dt] időintervallumban tartózkodik ott. (3 hajóhossz + fél hajóhossz, mert a hajó orrától és tatjától számoljuk a 3 hossz ráhagyást).
- Hasonlóan, a saját hajó esetén ez dT = 3.5 * L / V, és [T-dT, T+dT] a keresett időintervallum.
- Ha a két időintervallum nem metszi egymást, akkor nincs figyelmeztetés.
- Ki tér ki?
- Ha 270° ≤ rd ≤ 360° vagy 0° ≤ rd ≤ 90°, akkor
- Ha dx > 0, a másik hajó mehet, a saját hajó lassít.
- Ha dx < 0, a sajét hajó mehet (óvatosan), a másik hajó lassít.
- Ha 90° < rd < 270°, akkor
- Ha m > M, akkor a másik hajó mehet (óvatosan), és a saját hajónak kell manővereznie.
- Ha M > m, akkor a saját hajó mehet (óvatosan), és a másik hajónak kell manővereznie.
Házi feladat: JUnit használata magasabb szintű tesztekhez
Készíts rendszerteszteket JUnit segítségével. A tesztesetek legyenek a fenti leírás szerintiek. A feladat beadási határideje a következő órát megelőző nap 8.00 óra. A feladatot a Coospace felületen kell beadni. A formátuma egy tömörített (zip) állomány, amely minimálisan tartalmazza a teszt forráskódját és a futási eredményt (erről készített dokumentumot, vagy képernyőképet). Javasoljuk a teljes projekt beadását (azaz az eredeti kódót és a teszteseteket együtt csomagoljuk be a projektállományokkal egyetemben), ez az értékelést is megkönnyíti.
Mi a teszt futtatásának eredménye?
Sikerült-e a tesztek segítségével valamilyen hibát felfedezni?
Rendszerteszt hiba
- Ha pont szemből jön a másik hajó, akkor lehet, hogy biztonságos oldaltávolság ellenére is figyelmeztetést kapunk.