2008/01/31

Hudson

Szóval ez igazán egy pazar cucc. (Egyébként egy Continous integration eszköz) Régebben (egy két éve) még a Continuum-ot nézegettem, akkor az még csak standalone-ként volt hajlandó futni nekem, és rengeteg adatbázis mütyürészést kellett véghez vinni, hogy elinduljon (azóta talán az is fejlődött). Ellenben ez csupán egy war, amit bedeployolok és megy.

Nálunk így megy: 5 percenként svn update-et nyom és ha változik valami fordít újra egy release-build-et és lefuttatja rajta a unit teszteket (Unitils rulez, ha változik a séma definíció a repositoryban, automatikusan felépít egy új adatbázist).

A Hudson-nak valami olyasmi a filozófiája, hogy én elvégzem a piszkos munkát (Ant-tal, Maven-nel, shell scripttel, bármivel), és ő az eredményt szépen megmutatja. Pl. megmondom neki, hogy az ANT task végén hol lesz az artifact, és ő azt szépen archiválja (nálunk a legutóbbi 10-et), ezek közül meg lehet jelölni bármelyiket hogy ne rotálódjon ki (tipikusan nálunk mindig a legutóbbi 10 build van fent, meg megjelölve az a régebbi, ami épp a megrendelőnél van). És persze, ha szar kerül a palacsintába, akkor email-t ír, telefonál, kárt ment, stb.

A fejlesztője nagyon nyomni akarja, ezért nagyon sűrün vannak belőle release-ek, és az egész interface kellemes hangulatot áraszt. Pl. értelmes hibaüzeneteket ír, és elmondja, hogy mikor mi a baj.

Szóval nem próbáltam végig az összes CI toolt, de ez elsőre nagyon használhatónak tűnt.

2008/01/17

Generics + reflecion

Tegnap ígértemhez híven: a generic típusok a bytecodeban benne vannak a deklarációs részben, csak a utasításoknál nincsenek. Reflecionnal tehát lekérdezhetőek.(Pontos speckó linket most nincs időm keresni, helyette itt a példakód.)

public class Main {

    public List<Double> list;

    public static void main(String[] args) throws Exception {
        Field field = Main.class.getDeclaredField("list");
        ParameterizedType ptype = (ParameterizedType) field.getGenericType();
        Type[] types = ptype.getActualTypeArguments();
        System.out.println(types[0]);
    }
}

2008/01/11

Toplink JPA bug

Mindig öröm, ha egy komoly termékben néhány órás szívással izolálni tudunk egy hibát, és végre kiderül, hogy nem mi voltunk a hibásak. Most az történt, hogy Joined table inheritance strategyt használtunk és left joint és a Toplink Essential a discriminator value-t inner join-nal kezelte. Magyarul nem lehet left joint csinálni, hiába írom be a querybe.. Ki próbáltam Hibernate JPA-val is (ugye milyen jó, hogy hipp-hopp váltogatni lehet a providerek között?), és azzal rendesen ment.

Akkor most bugreport és native queryk használata a bugfixig.

2008/01/07

Unitils tapasztalatok

Régóta nem írtam már ide, pedig jócskán felgyűltek a témák. Az egyik ilyen az Unitils bevezetése az egyik projektünkbe. Az Unitilsnek Kocka egyik blogbejegyzése nyomán kezdem utána nézni.

Az Unitils a Junit3,Junit4 és a TestNG keretrendszerek mindegyikével házasítható, ezeknek a teszt környezeteknek funkcióihoz adnak hozzá a moduljai. A Unitils moduláris felépítésű, mi három modulját használjuk:

database
A database modul egy adott környvtárban található sql szkripteket sasolja. Ha valami is vátozik, akkor az adatbázis teljes sémáját bedarálja, és újra futtatja a szkripteket. Nagyon praktikus olyankor, amikor a sémát SVN-be tároljuk, de többen is szerkesztgetjük.

dbunit
Ez igazából a dbunit-ra egy wrapper modul. a @DataSet és @ExpectedDataSet annotációkkal jelölhetjük meg a teszteinket, és ezekkel adhatnk meg egyszerű XML-eket, amikben a teszthez szükséges adatbázis tartalom van. Pl.

ServiceOneTest.xml
<dataset>
<customer id="1" name="asd">
</dataset>

ServiceOneTest.testOne-result.xml
<dataset>
<customer id="1" name="changed">
</dataset>

Elég kényelmes dolog, de van egy fontos tulajdonsága. Az előző modul a séma létrehozása után alapból az összes constraint-et disabled-re állítja. Ez egyfelől kényelmes, mert az XML-ekben tényleg csak azt az adatot kell beleírni, amit tesztelünk (esetünkben a customer name tulajdonságát), és pl. a company mezőt nem, mégha elvileg foreign key lenne is rá. Persze ez azt is jelenti, hogy a constraint-eket ilyenkor nem teszteljük.
(Megadhatjuk azonban azt is, hogy a constraintek maradjanak).

ejb3
Ez a harmadik modul amit használunk, saját fejlesztés (nagyon egyszerű új modulokkal kiegészíteni a Unitils-t). Ha talál egy @EJB annotacíót a unit tesztünkbe, akkor oda injektálja az EJB-t, és az EJB-be is ellenőrzi az annotációkat és oda is injektál mindent (pl. EntityManager). Nagyon kényelmes, mert gyakorlatilag az egész EJB oldalt standalone unit tesztekkel tudjuk tesztelni. Ha igény van rá, talán majd publikáljuk is.

Ezenkívül van még Spring, Hibernate és EasyMock-ot támogató modulja is, azokat mi nem használtuk. Viszont standalone alkalmazáshoz is viszonylag kis fájdalommal hozzá lehetett gyógyítani (egy migráló szkript használja a Unitils database modulját arra, hogy ő is mindig az aktuális adatbázis sémán dolgozzon). A forrása is szép, mindenütt interface-k vannak, sok helyen lehet változtatni az implementációt.

Nyilván ezzel is előfordulnak szívások, de összességében csak ajánlani tudom. Használata Junit 4.4-től csak annyi, hogy a tesztet meg kell annotálni egy @RunWith(UnitilsJUnit4TestClassRunner.class) annotációval.