Unit testing - PinkReapers/faup GitHub Wiki
Hogyan tesztelünk?
Unit tesztünk alapja a main függvény visszatérése. Minden egyes unithoz írunk egy külön test c-fájlt, amelyben megvizsgáljuk a metódusait. Ha 0-val tér végül vissza, akkor a teszt sikeresen lefutott, ellenkező esetben hiba volt.
Előkészületek:
A faup project cmake-et használ. Feltérképezve a könyvtársturktúrát, az src mappán belül találjuk a lib könyvtárat, amiből tesztelni fogunk, és a a tests mappát, ahol a teszt fájlok, és a hozzá kapcsolódó konfigurációk láthatók. Számunkra fontos a CmakeLists.txt, ahol megadhatjuk a futtatandó teszteket.
A tesztek futtatásához a ctest toolt fogjuk használni, amely a cmake mellé jár alapértelmezésként. Első lépésként tudnunk kell, hogy hogyan fordítjuk le a projectet.
Fordítás:
A README-ből megtudtam, hogy az első fordításhoz ki kell törölni a cmake cache fájlát a fő mappából. Ezek után létrehozunk egy build mappát, és belépünk oda. Nyitok egy terminal-t, és a következő parancsokat adom ki benn: cmake make (sudo make install) Ez utóbbi csak a telepítéshez szükséges. A cmake megcsinálja a megfelelő konfigurációt, majd a make lefordítja a faup-ot.
Tesztek futtatása:
Hogy lássuk hol állunk, az előző lépések folytatásaként adjuk ki a ctest parancsot a build könyvtárban
11 unit tesztje van készen, melyek közül mindegyik sikeresen lefutott.
Új tesztek írása:
A src mappából kiválasztottam a lib/decode.c – t. Ezt a unitot fogom letesztelni a bemutatóm keretében. Ehhez első lépésként beírom a tests mappa CMakeLists.txt fájlába a következőket:
add_executable(decode-tester decode-tester.c) target_link_libraries(decode-tester ${FAUP_LIBRARY} ${CMAKE_DL_LIBS}) add_test(DecodeTester decode-tester)
Ezzel megmondom a cmake-nek, hogy adjon hozzá DecodeTester névvel egy új tesztet, amely forrása a decode-tester.c fájlban helyezkedik el.
Írjuk meg a decode.c-t, amely a tesztünket tartalmazza. Első lépésként csak visszatérek egy üres main függvényből 0-val. A bevezetés fényében ennek sikeres tesztnek kell lennie.
Elmentem, és belépek a fő mappában lévő build mappába. Kiadom a ctest parancsot, hogy lefuttassam a teszteket. Ekkor csak az eddig 11 tesztet látom. Kiadom a cmake, majd utána a ctest parancsot. A következő fogad:
(megj: amikor fotóztam, akkor még Mytest-nek hívtam, utána pedig rájöttem mi a hiba a decode-dal, és már nem tudtam repodukálni :) )
Miért van ez a hiba?
Több óra kísérletezés után végül Áron hozta a megvilágosodást. Amikor elmagyaraztam neki a dolgot, akkor jött a megvilágosodás, és emiatt építettem így föl a leírásom. Amit nem számoltam bele, hogy a cmake önmagában nem fordítja le a kódot, így a helyes sorrend a következő: cmake .. make ctest Ezután már a bővült tesztgyüjteményt látjuk, ráadásul le is fut a teszt:
Győződjünk meg a helyességről. Átírom a decode.c-t, hogy 1-gyel térjen vissza a main függvénye. Majd lefordítom, és futtatom a tesztet a fent ismertetett módon.
Értékelés: ezt az eredményt vártuk. Meggyőződhettünk róla, hogy tényleg a main visszatéréstől függ a teszt passed vagy failed értékelése.
Írjunk valós tesztet
Ehhez include-olom a faup/decode headerjét, és meghívom a tesztelni való függvényeit. A példában az is_ipv4-et választottam ennek bemutatására, mely bemenetként egy karakterláncot, és ennek hosszát várja, és megállapítja, hogy a megadott lánc ipv4 cím-e.
A tesztelési stratégiám a következő:
Megnézem egy korrekt ip – korrekt hossz párosra. (várt: true) Megnézem egy korrekt ip – (másik) korrekt hossz párosra. (várt: true) Megnézem egy korrekt ip – túl hosszú hossz párosra. (várt: false) Megnézem egy korrekt ip – túl rövid hossz párosra. (várt: false) Megnézem egy inkorrekt ip – korrekt hossz párosra. (várt: false) Megnézem egy inkorrekt ip – túl hosszú hossz párosra. (várt: false) Megnézem egy inkorrekt ip – túl rövid hossz párosra. (várt: false) Megnézem egy domain – korrekt hosszra (várt: false)
Megnézve a többi teszt felépítését bevezetek egy ret változót, amit kezdetben 0-ra állítok. Minden hívásnál megvizsgálom, hogy az elvárt feltétel teljesült-e. Ha nem, akkor növelem 1-gyel a ret változó értékét. A main visszatérésének a ret változót állítom be. Ha minden hiba nélkül lefutott, akkor 0-t ad vissza. Ha volt hiba, akkor azt, hogy hány darab volt.
A megírt kód hozzá: ` #include <stdio.h> #define __USE_XOPEN_EXTENDED #include <string.h> #include <faup/faup.h> #include <faup/decode.h> #include <faup/hash/hash.h> #include <faup/hash/htable.h>
int main(int argc, char **argv) { int ret = 0; if (!is_ipv4("192.168.1.12", 12)){ //correct ipv4 ret++; } if (!is_ipv4("192.168.120.12", 14)){ //correct ipv4 ret++; } if (is_ipv4("192.168.1.12", 15)){ //bigger length ret++; } if (is_ipv4("192.168.1.12", 2)){ //lower length ret++; }
if (is_ipv4("2001:db8:a0b:12f0::1", 20)){ //ipv4 ret++; } if (is_ipv4("2001:db8:a0b:12f0::1", 12)){ ret++; } if (is_ipv4("2001:db8:a0b:12f0::1", 11)){ ret++; }
if (is_ipv4("http://what.com", 15)){ //domain ret++; } if (is_ipv4("http://what.com", 16)){ //domain ret++; } if (is_ipv4("http://what.com", 20)){ //domain ret++; } return ret; } ` Futtassuk le!
Láthatjuk, hogy lefut sikeresen.
Egy kis csalást követtem el…
Vegyük a következő kódot:
if (is_ipv4("192.168.1.12", 10)){ ret++; }
Ennek false-szal kellene visszatértni, ám ha így lefuttatjuk a tesztet, akkor az failed állapotba ér:
Értékelés
Ez egy logikai hiba! Ilyenkor élesben nyitok róla egy issue ticketet, hogy a fejlesztők ki tudják javítani. Ez egy jó példa rá, hogy miért érdemes tesztet írni