A következő címkéjű bejegyzések mutatása: FitNesse. Összes bejegyzés megjelenítése
A következő címkéjű bejegyzések mutatása: FitNesse. Összes bejegyzés megjelenítése

2011. november 1., kedd

Adatforrás kialakítása Selenium tesztekhez

A mostani cikkemben a FitNesse és a Selenium keretrendszerek egy olyan előnyös ötvözéséről fogok blogolni, amit jómagam találtam ki a Selenium-os tesztelés megkönnyítésére!

Gyakori igény, hogy szükségünk lenne a Selenium tesztjeink eltérő adatokkal való futtatására. Az adatok tárolására elsőre jó megoldásnak tűnhet egy egyszerű csv, properties vagy excel táblázat használata, azonban több száz teszt esetén ezek nem lesznek karbantarthatóak (gondoljunk csak bele, hogy milyen nagy állományok jönnének létre), főleg amikor eltérő környezetekhez eltérő adatokat kellene használnunk. Egy javítási mód lenne ha nem egy nagy excel táblázatot kezelünk, hanem környezetenként (esetleg tesztenként) létrehoznánk egyet-egyet, azonban egy idő után ezzel is karbantartási problémák merülnének fel, mivel a sok állomány manuális kezelése elég nehézkes!

A felvázolt problémára szerintem egy webes oldalstruktúrát használó, HTML táblázat alapú adatforrás jelenthetné a megoldást. Mivel kifejezetten erre a célra nem készült még keretrendszer, úgy gondoltam, - az eredeti felhasználási területétől egy kicsit elrugaszkodva - hogy bevetem a FitNesse-t!

Excel alapú Selenium adatforrás

Bár nagyszámú teszteset esetén az excel alapú adatforrás véleményem szerint nem a legmegfelelőbb választás, bizonyos esetekben megfelelő alternatíva lehet az egyszerű és gyors kezelhetősége miatt. Az excel alapú adatforrás megvalósításának részleteiről itt olvashatsz bővebben.

FitNesse alapú Selenium adatforrás

A Selenium és a FitNesse integrációjával nemcsak az adatforrás problémakörre kapunk megoldást, hanem egy-két nagyon hasznos feature-re is szert teszünk:

  • Tesztjeinket a FitNesse webes felületéről is elindíthatjuk és megtekinthetjük lefutási eredményeket.
  • A FitNesse wiki oldalak verziózásából adódóan, visszaállhatunk egy korábbi adatforrás verzióra.
  • A tesztek definiálása és az adatok megadása mellett, akár szöveges megjegyzéseket is hozzáadhatunk az adatforrás oldalaihoz.
  • Visszakövethetők azok a felhasználók, akik az adatforrás oldalain módosításokat végeztek.
  • Az oldalak szerep alapú korlátozásának lehetősége az olvasás, írás és teszt futtatás tekintetében.

A FitNesse alapú adatforrás kialakításának további előnye, hogy az eltérő környezetekben futó tesztek (pl.: Teszt, Fejlesztői, Integrációs) nemcsak eltérő adatforrásokat, hanem egyedi paramétereket is használhatnak melyeket a hierarchia tetején is definiálhatunk az öröklődésük miatt.


A fenti ábra a FitNesse segítségével definiált, Selenium tesztekhez kapcsolódó adatforrások elhelyezkedését mutatja. A RootSuite tartalmazza a környezetek szerinti suite-okat (TestSuite, DevSuite, IntSuite), melyek a tesztesetek adatforrásait tartalmazzák. A kialakított adatforrás felépítés következtében, a tesztek a gyökér suite-nál egyszerre, vagy környezetenként külön-külön is indíthatók. Érdemes a RootSuite-nál meghatározni a Fixture classpath-t és a használni kívánt böngésző típust (driver), a környezeteknek megfelelő suite-oknál pedig a baseUrl-t, mivel a szülő csomópontoknál megadott paramétereket tovább öröklődnek a gyerekek felé.

Az adatforrások létrehozása megegyezik a FitNesse teszt táblázatok felvételével, a különbség annyi hogy a tesztmetódusok visszatérési értékét nem ellenőrizzük, így azok egységesen true-val térnek vissza. Természetesen a sikertelenül lefuttatott tesztesetek ilyenkor is kijelzésre kerülnek. 


A környezetenként eltérő ${baseUrl} és a böngésző meghajtóhoz tartozó ${driver} változóként kerül definiálásra, mivel az értékek a hierarchiában feljebb lévő suite-nál kerültek definiálásra.


Az elkészített wiki oldalhoz tartozó adatokat a LoginTest, testLoginFunction metódusa használja fel. A tesztosztály a TestBase ősosztályból származik, ahol inicializálásra kerül a baseUrl és a böngésző típus. A TestBase egyben egy ColumnFixture is, amit a RootSuite-nál definiált classpath bejegyzés köt össze a wiki oldallal.
public class TestBase extends ColumnFixture {

 protected Selenium selenium;
 protected WebDriver driver;

 protected void beforeTestCase(String[] fixtureArgs) {
        String baseUrl=fixtureArgs[0];
        String driverName=fixtureArgs[1];
        
        if(driverName.toLowerCase().equals("firefox")){
            driver = new FirefoxDriver();
        }
        else if(driverName.toLowerCase().equals("chrome")){
            driver = new ChromeDriver();
        } 
        //...

        selenium = new WebDriverBackedSelenium(driver, baseUrl);
    }

 protected void afterTestCase() {
  driver.close();
 }
}
Az így kialakított felépítés nem egy hagyományos JUnit teszteset, így a beforeTestCase() ill. afterTestCase() metódusokat a tesztmetódusban kell meghívni. Az afterTestCase() metódus a finally blokkban kapott helyet, így annak lefutása mindig garantált, azaz a Selenium által megnyitott böngésző egy esetleges kivétel esetén is bezárásra kerül. A teszt elindításával a LoginTest publikus mezői megkapják - a táblázat minden sorára lefutva - a wiki táblázat megfelelő mezőinek értékét, megoldva a külső adatforrás értékeinek a felhasználását.
public class LoginTest extends TestBase {

 public String userName;
 public String password;

 public boolean testLoginFunction() throws Exception {
  beforeTestCase(getArgs());
  try {
   selenium.open("/portal/ep/home.do");
   //További selenium parancsok vagy PageObject-ek használata
  } finally {
   afterTestCase();
  }
  return true;
 }
} 
Ezzel egyelőre véget is ért a Selenium-os cikksorozatom. Ha hasznos infókat tartalmazott a számodra, esetleg további kérdéseid lennének a Seleniummal kapcsolatban, írj egy kommentet!

2011. augusztus 6., szombat

FitNesse tesztek indítási lehetőségei

Egy korábbi bejegyzésemben a FitNesse használatát mutattam be egy példán keresztül, a mostani cikkben pedig az elkészített teszt futtatási lehetőségeit fogom ismertetni.

A tesztek indítási módjaiban közös, hogy meg kell adni a típust (suite vagy teszt) valamint az útvonallal specifikált nevet, majd opcionálisan a végrehajtás eredményének kimeneti formátumát és a Fitnesse web-szerver által használt portot.

FitNesse tesztek wiki oldalról történő indítása

A tesztek indításának talán legegyszerűbb módja a wiki oldalról történő futtatás. A FitNesse web-szervert, a FitNesse gyökér könyvtárából indítsuk el a java -jar fitnesse.jar –p 6666 paranccsal, majd keressük ki a futtatni kívánt tesztet vagy suite-ot és kattintsunk a baloldali menüben a suite ill. test gombra. 

Indítás után, a típusnak megfelelően megjelenik egy ?test ill. ?suite paraméter az url-ben, melyek begépelésével a futtatás direkt módon is végrehajtható. Ha a tesztek eredményeit nem a wiki oldalon keresztül, hanem egy meghatározott formátumban szeretnénk elérni, használjuk a format url paramétert a text, xml vagy html értékekkel. pl.: ExampleTestSuite?suite&format=xml

A böngésző címsorában található context-root utáni URL-t, mint útvonallal specifikált nevet használhatjuk fel a suite-hoz tartozó összes teszt (ExampleTestSuite) vagy egy kiválasztott teszt (ExampleTestSuite.ExampleTest) futtatásához a további eseteknél.

FitNesse tesztek indítása parancssorból

A konzolról történő indításhoz a FitNesse gyökérkönyvtárából adjuk ki a java -jar fitnesse.jar -p 6666 -c "ExampleTestSuite?suite&format=xml" -d "/usr/local/Fitnesse" parancsot. A -c opcióval definiálhatjuk a futtatni kívánt tesztet és a kimeneti formátumot, a -d kapcsolóval pedig a munka könyvtárat állíthatjuk be.

FitNesse tesztek indítása Java kódból

A Fitnesse tesztek java kódból történő indításához, az Eclipse/Run Configurations menü alatt a java kódhoz tartozó konfiguráció Arguments tabján, a Working directory résznél adjuk meg a FitNesse munka könyvtár helyét.


A fejlesztőeszköz beállítása után, a tesztek Java kódból történő indításához az alábbi kódrészlet használható fel.
import fitnesse.Arguments;
import fitnesseMain.FitNesseMain
    
    ...
    
    public void testerMethod() throws Exception {
        Arguments arguments = new Arguments();
        arguments.setInstallOnly(false);
        arguments.setOmitUpdates(true);
        arguments.setPort("6666");
        arguments.setCommand("ExampleTestSuite.ExampleTest?test");
        arguments.setRootPath("/usr/local/Fitnesse");
        FitNesseMain.dontExitAfterSingleCommand = true;
        FitNesseMain.launchFitNesse(arguments);
    }
FitNesse tesztek indítása Ant használatával

Az Ant-tal történő futtatást akkor érdemes választani, amikor a FitNesse tesztek indítását a build folyamat részeként, automatizáltan akarjuk végrehajtani. Az alábbi kódrészleten egy ant build fájl tartalma látható, ahol is a start target végzi el a kiválasztott tesztek indítását.
<project basedir="/usr/local/Fitnesse" default="start" name="Test">  
 <path id="classpath">
  <fileset dir="/usr/local/Fitnesse" includes="**/*.jar">
  </fileset>
 </path>   

 <target name="start">        
  <java failonerror="true" fork="true" jar="/usr/local/Fitnesse/fitnesse.jar">       
   <arg value="-p"></arg>      
   <arg value="6666"></arg>
   <arg value="-c"></arg>                
   <arg value="ExampleTestSuite?suite&format=xml"></arg>     
  </java>
 </target> 
</project>
FitNesse tesztek indítása a Hudson CI szerver segítségével

A Hudson ill. Jenkins Continuous Integration szerverek szintén lehetőséget nyújtanak a FitNesse tesztek futtatásához. A folyamatos integráció lényege, hogy a fejlesztők folyamatosan integrálják a munkájukat egy központi szerveren, ahol is a build folyamat után ellenőrzéseknek vetik alá a szoftvert mint terméket. Ilyen ellenőrzések lehetnek a statikus kód ellenőrzések, teszt lefedettség vizsgálatok vagy a FitNesse tesztek futtatása. Az ellenőrzések eredményét a Hudson képes megjeleníteni, így folyamatosan követhetjük a projekt állapotát és szükség szerint időben beavatkozhatunk!

Itt jegyezném meg, hogy a Hudson/Jenkins az egyik kedvenc eszközöm, ezért hamarosan a folyamatos integráció témakörben is fogok blogolni... :)

A rövid áttekintés után térjünk vissza FitNesse tesztek indításához. A Hudson plugin manager oldalon telepítsük fel a FitNesse plugint, majd hozzunk létre egy új jobot a projektnek. A build résznél válasszuk ki az ”Execute Fitnesse tests” opciót, majd a ”Start new Fitnesse instance as part of build”-et bejelölve töltsük ki a mezőket az alábbi ábra szerint:

 
Ahhoz, hogy a FitNesse tesztek lefutási eredményét riportként is megtekinthessük, állítsuk be a FitNesse result fájlt, a ”Post build action” résznél is. Figyeljünk arra, hogy az eredmény fájl útvonalát a Hudson workspace-en belül adjuk meg!


Mentsük el a beállításokat és futtassuk a létrehozott job-ot, majd tekintsük meg a helyes beállításokról tanúskodó konzol naplót.


A FitNesse teszteket sokféleképpen, de mégis hasonló séma alapján indíthatjuk, így megvan arra a lehetőségünk, hogy mindig a felmerült igényekhez legjobban illeszkedő módszert válasszuk!

A következő cikkemben még mindig a tesztelési témakörnél maradok, de már egy másik remek teszteszköz ismertetésére fogok rátérni!

2011. július 19., kedd

FitNesse, a wiki alapú tesztkeretrendszer

A FitNesse egy acceptance tesztelési keretrendszer, melynek célja hogy a teszteket készítő fejlesztők és a területi szakértők közti szakadékot megszüntesse, azáltal hogy a szakértők számára is elérhetővé teszi a tesztek kezelését és végrehajtását.

Működésileg egy saját web-szerveren futó wiki site, amely strukturált és könnyen olvasható formában teszi elérhetővé a teszteket. A teszteket wikis formázással megadott táblázatok reprezentálják, melyekhez egy-egy Fixture java osztály tartozik. A Fixture osztályok teremtik meg a kapcsolatot a wikis táblázatok és a java tesztkód között. A táblázatok input adatokat és a várt output adatot tartalmazzák, valamint a Fixture kód elérhetőségét. A FitNesse egyszerű felépítése és koncepciói nagyban hozzájárulnak a kiváló használhatóságához, melyek lehetővé teszik széleskörű alkalmazását!

FitNesse telepítése és a menüstruktúra ismertetése

A FitNesse telepítése és indítása nagyon egyszerű! Töltsük le a legfrisebb fitnesse.jar-t a FitNesse hivatalos oldaláról, majd másoljuk be abba a könyvtárba ahova telepíteni szeretnénk, végül adjuk ki a java -jar fitnesse.jar -p 6666 parancsot. Amennyiben a 80-as port már foglalt, a –p opcióval jelölhetünk ki egy szabad portot. A parancs futtatása után létrejön a FitNesseRoot nevű könyvtár a sablon wiki oldalakkal feltöltve, melyet a http://localhost:6666/ címen tekinthetünk meg.


Rövid áttekintés a baloldali menük funkcióiról:
  • Edit: Az aktuális - jobb oldalon megjelenő - wiki oldal tartalmának szerkesztése.
  • Properties: Az aktuális wiki oldal tulajdonságainak szerkesztése.
    • Page Type: Az oldal típusának meghatározása, ami lehet egyszerű wiki oldal, teszt oldal vagy suite oldal.
    • Actions: A baloldalt megjelenő akció funkcionalitású menüelemek meghatározása.
    • Navigation: A baloldalt megjelenő navigációt biztosító menüelemek kiválasztása.
    • Securtiy: Biztonsági megszorítások az aktuális wiki oldalra vonatkozólag.
  • Refactor: Az aktuális wiki oldal törlése, átnevezése vagy új helyre mozgatása.
  • Where Used: Az aktuális wiki oldal más oldalakon történő hivatkozásait mutatja.
  • Search: Kifejezés keresése a wiki oldalakon.
  • Files: A fájlrendszerbeli könyvtárstruktúra áttekintése és böngészése.
  • Versions: Az aktuális wiki oldal módosítás utáni verzióinak megtekintése és visszaállási lehetőség egy korábbi verzióra. (rollback)
  • Recent Changes: A legutóbbi változások teljes wiki struktúrát tekintve.
  • User Guide: Általános ismertető a FitNesse keretrendszerről.
  • Test History: Az elindított tesztek sikerességéről kaphatunk információkat.
  • Suite: A suite oldalak esetén megjelenő menüelem, amivel a suite alatt lévő teszteseteket futtathatjuk a wiki oldalon keresztül.
  • Test: Az adott oldalhoz tartozó teszteset futtatása a wiki oldalról indítva.

FitNesse Suite létrehozása és konfigurálása

Az ExampleTestSuite oldal létrehozásához kattintsunk a cím melletti ”add child” linkre majd adjuk meg az oldal típusát és nevét, végül kattintsunk az add gombra.


Ahhoz hogy a felvett oldalt használni tudjuk válasszuk ki az Edit menüt, majd a megjelenő wiki szerkesztő felületen írjuk be az oldal nevét, esetleg töröljük a számunkra szükségtelen részeket az oldalról.


A mentés után megjelenő oldalon az ExampleTestSuite[?]-re kattintva létrehozhatjuk magát a wiki oldalt. Ha az újonnan létrehozott oldal baloldali menüjében nem jelent volna meg a Suite menüelem, akkor a Properties menü alatt módosítsuk a megfelelőre.


Az ExampleTestSuite oldalon kerül definiálásra a classpath valamint két Fitnesse változó a define kulcsszó megadásával. A classpath sorokkal a szükséges könyvtárak és a Fixture kódot tartalmazó class ill. jar helyét adhatjuk meg, a define kulcsszóval pedig a teszteseteknél is használni kívánt változókat definiálhatjuk. Azáltal, hogy a classpath és a define értékeket az ExampleTestSuite-nál adjuk meg, a hierarchiában alatta lévő suite-okra és tesztekre (pl.: ExampleTest) is tovább öröklődnek, bár az alsóbb szinteken szükség szerint felüldefiniálhatók.



FitNesse teszt létrehozása és futtatása

A következőkben egy egyszerű String összefűzési funkció tesztelését fogom ismertetni a ColumnFixture felhasználásával.

Az ExampleTestSuite véglegesítése után, a suite alá vegyünk fel egy ExampleTest oldalt az ”add child” linkre kattintással úgy hogy az oldal típusa test legyen, majd hozzuk létre a tesztesethez tartozó táblázatot. A táblázat első sorában definiáljuk a Fixture osztályt (MyFitnesseTest), valamint a felhasználni kívánt változókat melyek a Fixture osztályban a getArgs() metódussal érhetők el. A táblázat második sora az oszlop neveket tartalmazza (username, password), melyeket a Fixture osztályban publikus mezőként kell megadni, valamint a tesztmetódust. (testConcatenation). A táblázat további sorai a bemeneti adatokat és a kimenet elvárt eredményeit tartalmazzák, melyek egy-egy teszt lefutásnak felelnek meg.

 


A teszthez tartozó Fixture osztály kódja az alábbi forráskódrészleten látható:
package fitnesse.example;

import fit.ColumnFixture;

public class MyFitnesseTest extends ColumnFixture{

    public String username;
    public String password;
    
    public String testConcatenation(){
        
        System.out.println(username);
        System.out.println(password);
        System.out.println("myVariable1: "+getArgs()[0]);
        System.out.println("myVariable2: "+getArgs()[1]);
        
        return new StringBuilder()
                    .append(username)
                    .append(password)
                    .append(getArgs()[0])
                    .append(getArgs()[1]).toString();
    }
}

Az elkészült tesztet az ExampleTestSuite oldalon látható suite gombra klikkelve vagy az ExampleTest oldal test gombjára kattintva indíthatjuk el, melynek eredményét egyből megtekinthetjük az oldalon.


FitNesse oldalstruktúra kialakítása

A tesztek végrehajtását teszt oldalanként vagy suite-onként van lehetőségünk elindítani. Egy suite, teszteket és további suite-okat tartalmazhat. A wiki oldal struktúrát úgy érdemes kialakítani, hogy készítünk egy gyökér suite oldalt ahova további suite oldalakat veszünk fel, majd az alsóbb szintekre helyezzük a tesztoldalakat. Ez a kialakítás azért hasznos, mert a suite-ok csoportba fogják a teszteket így a tesztek futtatását is ezen csoportok alapján hajthatjuk végre. A suite-os csoportosítás további előnye, hogy a classpath ill. változó deklarációk is öröklődnek a hierarchiában lentebb található suite-okra és tesztekre, így azokat elég csak a felsőbb szinten megadni. Persze egy alsóbb szinten deklarált változó mindig erősebb hatókörrel bír, így névegyezés esetén az alsóbb szintű fog érvényre jutni.


Zárszó

A wiki-s táblázat alapú tesztek az olvashatóságot és a karbantarthatóságot tekintve is előnyösebbek a programozott tesztekkel szemben, igaz a kiegészítő kódok elkészítésére időt kell szánni.

A cikk folytatása hamarosan következik...!