2014. május 13., kedd

A tiéd mekkora?

Hú, de régen nem írtam semmit. Mostanában valami rettenetesen sokféle dologgal foglalkoztam a melón kívül, most éppen fordítóprogramot javítok, mostanában agenteket buherálok, még mindig dolgozok a cloudstack körül is dolgozgatok, tanulok eztazt és persze írok a wikipédián. Ennek eredményeként nem kicsit lehet elhanyagolva ez a szegény blog. Köszi mindenkinek aki ennyi idő után se törölte az RSS olvasójáról. Gondoltam visszaszokásként tesztelés témakört rúgnám tökön.

Anekdota bemelegítésnek: Az első napon a kb első munkahelyemen súlyos hibát követtem el. Belenéztem a forráskódba és azt mondtam: próbáljuk ki! Erre az über-führer egyből az első napon lecseszett: "Laci, nincs időnk játszani, dolgozni kell!" Ilyen súlyos hajótöréssel kezdődött az IT "karrierem", most már mindent értetek.

Az embernek kicsit bizonytalannak kell lennie saját képességeiben ahhoz, hogy nekilásson minden egyes csavart megvizsgálni. A tesztelés az a dolog, ami zseniknek nem való. Zsenit viszont nagyon keveset láttam eddig, önmagát zseninek tartó hülyét viszont nagyon sokat.

Unit tesztek


A unit tesztelésnél az szokik az első kérdés lenni, hogy mit teszteljünk. Nekem általában véve az a véleményem a dologról, hogy minden mozgó alkatrészt érdemes kipróbálni. Na és mi a fészkes lehet az a mozgó alkatrész? Néhány példát felsorolnék:
  • A java kód, az nyilvánvalóan, de nem itt ér véget a lista
  • MyBatis nevű rémálomban az SQL utasításokat kipakolhatod egy XML-be. Ami abban az XML-ben van, az mozgó alkatrész.
  • JPA-ban tipikusan annotációkat tesznek a perzisztens osztályokra. Ezek az annotációk határozzák meg, hogy melyik táblába, melyik oszlopba kerül az adat, tehát az is mozgó alkatrész.
  • El ne felejtsük: adatbázis séma, tárolt eljárások
  • A HTML kód és benne a sok-sok juvaszkript
  • ... satöbbi
A unit tesztek annyira elég, hogy tudd, az a pár sor amit leírtál, annak úgy a kontextusból elkülönítve képes megcsinálni azt, amire számítottál a teszt írásakor. Ez olyan, mint ha biciklid egy alkatrészét vizsgálnád meg, pl hogy nem ereszt-e a belső, nincs megrepedve a váz, nincs nyolcas a kerékben, satöbbi.

Én szeretem úgy számon tartani a mozgó alkatrészeket, hogy ha ránézek egy ilyen alkatrészre, akkor meg tudjam mondani hogy melyik unit teszt fog elfeküdni ha elszúrom és néha ki is szoktam próbálni, hogy igazam volt-e. Ezt általában az olyan projecteknél lehet megcsinálni, amelyiken az elejétől kezdve írtak teszteket a kedves emberek.

Az összes unit teszt sikere együttesen sem jelenti azt, hogy az alkalmazás valami értelmeset fog csinálni, vagy hogy egyáltalán el fog tudni indulni.

Talán emiatt is, de sokan tagadják, hogy a unit teszteknek lenne elegendő haszna illetve bármi értelme is. A unit teszt ugyanis néha nehéz. Pár példát említenék:
  • Van olyan kód, ami nem tesztelhető könnyen automatikusan. Tipikusan akkor, amikor a kód kicsi darabja nincs egészen elkülönítve a többitől. Ilyen amikor egy globális változón múlik a számítás eredménye vagy egyáltalán a működőképessége.
  • Környezeti beállításokra épül, például az operációs rendszerre feltelepített csomagokra vagy beállításokra. Ezt a Linuxerek éppen olyan gyakran követik el, mint a Windowserek.
  • Hálózati erőforrásokat használ, például muszáj hozzá egy X adatbázis, Y MQ vagy Z webservice, vagy egyáltalán csak be van hardkódolva egy hostnév.

A szoftvert tehát úgy kell felépíteni és a kódot úgy kell megírni, hogy tesztelhető legyen, amennyiben ez cél. Ezek néha nehezen leküzdhető akadályok, de (magánvélemény) nem annyira nehezek, mint amennyire ritkán fordul elő. A fenti nehézségeken kívül például az a pszichológiai oka, hogy triviálisnak tűnik a kód. Már volt velem olyan többször, hogy nekiláttam megírni a tesztet egy triviálisnak tűnő kódon, aztán a teszt futtatása közben jöttem rá hogy elszúrtam.

Ha a tesz nem megy át, akkor vagy nem jó a kód, vagy nem jó a teszt, vagy esetleg mindkettő rossz.
Ha átmegy a teszt, akkor vagy mindkettő jó, vagy mindkettő rossz. :-)

Mi mekkora?


A unit teszteknél szokás mérni a tesztek lefedettségét is és ebben a kérdésben szokott felvetődni, hogy mekkora a teszt lefedettsége egy adott projektnek vagy hogy mennyinek kell/kellene lennie. Ez egy nagyon nehéz vallás-politikai és etikai kérdés, tele morális csapdákkal és elméleti buktatókkal, a különböző ideológiai irányzatok és etnikai csoportok ellentéteiről nem is beszélve.
A lefedettség olyan technikai korlátokba ütközik, mint pl a java checked exceptions. Egyes kivételeket hiába kell levédeni, tulajdonképpen vagy soha nem jönnek, vagy csak extrém esetekben. Másik példa lehet Util osztályok akár default, akár implicit és levédett konstruktora: soha nem fog futni, mert Util osztályt soha nem példányosít az ember. Ilyen módon amikor valaki 100 százalékot makkan, akkor az hmmm... felveti a kérdést hogy hogyan érti. Nekem úgy tűnik, 70-80 százalék között van általában a unit tesztek számára kényelmesen elérhető ágak száma.

Na ettől azért általában rendesen távol állunk, ha szétnézel open source projektek között, viszonylag ritka a jelentősebb (akár 10% feletti) lefedettség. Izgi.

No, legközelebb majd az integrációs tesztekről valamit.