Az API-k általában jól meghatározható bemenettel és kimenettel rendelkeznek, alkalmat biztosítva automatizált tesztek generálására. Ezért is előny, ha egy webalkalmazásnál az adatokat, adatszerkezeteket egy API biztosítja, jól elkülönítve a felületet leíró szerkezetektől, rendszerektől. Általában ezek az adatok egy adatbázisból az API-n keresztül esetlegesen az API által manipulált formában kerülnek a klienshez.
Ilyenkor az első feladat, hogy biztosítsunk egy olyan teszt adatbázist, ami megegyezik az éles adatbázissal, de bármikor könnyedén fel tudunk építeni. Felmerülhet sok kérdés, például akkor, ha az adatbázishoz nem csak az API-n keresztül lehet hozzáférni, ami vagy hiba, vagy az adott rendszerhez át kell szabni a tesztelést. Egyelőre azt feltételezem, hogy kizárólag az API-n keresztül történnek az adatbázis műveletek. Hozzá kell tennem, hogy mi abban a szerencsés helyzetben vagyunk, hogy a szolgáltatásunkban, alkalmazásunkban nincs külső függőség, így könnyedén tudjuk automatizálni a tesztjeinket.
A fentieknek megfelelően egy teszt adatbázist kezelő scriptet készítettem.
$ ./testdb.py -h
Usage: testdb.py [options]
Options:
-h, --help show this help message and exit
-s PATH, --struct_path=PATH
read descriptor struct.json file from PATH
-o TYPE, --output-type=TYPE
generate output by TYPE
-c COMMAND, --command=COMMAND
run test with COMMAND
-q, --quiet don't print status messages to stdout
--host=HOST database connect host
Működésének folyamata:
- Létrehozzuk az adatbázist, ami ahhoz kell, hogy el tudjuk indítani az adott alkalmazást vagy szolgáltatást.
- Lefuttatjuk a scriptet "read" paranccsal, amely a megadott json fájlba leírja milyen táblákba, milyen adatokat kell beilleszteni.
- Amennyiben tesztelni szeretnénk az adatbázissal, akkor nincs más hátra, mint felépíteni az adatbázist:
- A teljes teszt adatbázis törlésre kerül.
- A sémakezelő létrehozza az adott branch-nek megfelelő adatbázist és a táblákat.
- Utána a script "insert" parancsával beillesztjük a szükséges rekordokat a már létrehozott json fájlból.
Ezt a teszt adatbázist minden etaponként/sprintenként karban kell tartani, azonban csak annyi a teendő, hogy a rekordokban történt változást/migrálást erre az adatbázisra is érvényesítenünk kell, a sémaváltozásokat meg úgy is a sémakezelő végzi.
Mivel van egy bármikor reprodukálható adatbázis, amit a tesztelés előtt és közben is akár újra és újra felépíthetünk, ezért neki is lehet kezdeni az API tesztelésének. Készítettem egy testapi.py scriptet, ami egy json fájlból olvassa ki a teszteket.
./testapi.py -h
Usage: testapi.py [options]
Options:
-h, --help show this help message and exit
-t PATH, --tests-path=PATH
read test *.json files from PATH
--test-file=FILE read test *.json file
-o TYPE, --output-type=TYPE
generate output by TYPE
-c COMMAND, --command=COMMAND
run test with COMMAND
-q, --quiet don't print status messages to stdout
-r, --resolve interactive conflict handling
--host=HOST database connect host
A teszteket leíró struktúra http kérések tesztelésére lett kialakítva, nézzünk egy REST kérésre példát:
[
{
"url": "testdb.host.hu",
"description": "Get user resource TEST",
"name": "UserResources",
"resetDb": true,
"tests": [
{
"resource": "/users/6/",
"method": "GET",
"data": "",
"expectedResult": {"userid": 6, "username": "test"},
"expectedResponseCode": 200
}
]
}
]
A testapi.py kezeli ezt a struktúrát, amiben például lehetőség van session kezelésére nem nyilvános API-k esetében, vagy lehetőséget biztosít bizonyos kulcsok mellőzésére (ami dátumok és idők kezeléséhez is jól jöhet). Nézzünk akkor egy tesztet:
$ ./testapi.py --test-file=test.json -t test/ -c api -o console
Load test: test.json
apitest/test.function_one
apitest/test.function_two
apitest/test.function_three
test_api_aux.TestAPI_Aux tests=6 errors=0 failures=0 Ok
----------------------------------------------------------------------
TESTS=6 ERRORS=0 FAILURES=0
Ran 6 tests in 0.016s
OK
Amint elrontunk valamit jelzi a hibát, jól látszik hogy a name kulcson nem a megfelelő nevet kaptuk vissza:
$ ./testapi.py --test-file=test.json -t test/ -c api -o console
Load test: test.json
apitest/test.function_one
--- expected
+++ server result
@@ -1,5 +1,5 @@
{
"company": "Virtual Call Center Ltd.",
- "name": "Jack Test",
+ "name": "Jack Test Bad Name",
"address": "Hackle Rise Street"
}
apitest/test.function_two
apitest/test.function_three
test_api_name.TestAPI_NAME tests=6 errors=0 failures=1 Error
----------------------------------------------------------------------
TESTS=6 ERRORS=0 FAILURES=1
Ran 6 tests in 0.014s
ERROR
Agilis fejlesztésnél igen gyakran változnak a dolgok, ezért nehéz karbantartani a teszteket. Amennyiben ez a változás a visszaadott eredményt érinti lehetőség van azt a -r opció segítségével interaktív módon érvényesíteni. Például ha bekerül az eredménybe egy új kulcs, akkor lehetőségünk van azt feloldani, így a test.json fájlba felülíródik a teszt, majd új futtatásnál már nem dob hibát:
$ ./testapi.py --test-file=test.json -t test/ -c api -o console -r
Load test: test.json
apitest/test.function_one
--- expected
+++ server result
@@ -1,5 +1,6 @@
{
"company": "Virtual Call Center Ltd.",
"name": "Jack Test",
+ "birth": "1980-03-12",
"address": "Hackle Rise Street"
}
Resolve conflit (y/n): y
apitest/test.function_two
apitest/test.function_three
test_api_name.TestAPI_NAME tests=6 errors=0 failures=1 Error
----------------------------------------------------------------------
TESTS=6 ERRORS=0 FAILURES=1
Ran 6 tests in 2.644s
ERROR
$ ./testapi.py --test-file=test.json -t test/ -c api -o console -r
Load test: test.json
apitest/test.function_one
apitest/test.function_two
apitest/test.function_three
test_api_name.TestAPI_NAME tests=6 errors=0 failures=0 Ok
----------------------------------------------------------------------
TESTS=6 ERRORS=0 FAILURES=0
Ran 6 tests in 0.022s
OK
API hívásokról van szó ezért könnyen automatizálhatóak ezek a teszt json fájlok létrehozása. Az API logokból könnyedén lehet generálni, ahogy mi is tesszük. Ez pedig azt jelenit, hogy a
Mozmill segítségével elkészített automatikus User Acceptance tesztek által generált API logokból mindig létre tudjuk hozni azoknak a forgatókönyveknek megfelelő API teszteket. Ami több dologra is jó:
- Szűkíti a hiba forrásának a helyét.
- Csökkenti a tesztelési időt.
- Példaalapú tesztelésnél jó eszközt biztosít a szerveroldalhoz.
- Elég egy helyen azaz a Mozmill-ben karbantartani a teszteket, hiszen sok más teszt abból generálódik le.
- Integration tesztekhez is segítséget nyújt.
Természetesen ez a mi rendszerünkre lett kitalálva, de könnyedén átalakítható más igényekre is. A mi esetünkben ezek a scriptek a következő előnyökkel járnak az API tesztelhetőségén kívül:
Előnyök:
- Példaalapú fejlesztést segíti, az API funkcionalitás elkészülte előtt írható rá teszt.
- Alkalmas más, például biztonsági vagy stressz tesztek generálására.
- Generálható felülettesztek által generált API logból.
- Egyes új módosítások feloldására alkalmas, ami megkönnyíti a karbantartást.
- Alkalmas junit formátumú xml kimenetet gyártani, ezért könnyedén beilleszthető például jenkinsbe.