Komplex példa 9. rész - Laravel Dusk

Attila | 2022. 04. 21. 17:30 | Olvasási idő: 3 perc

Címkék: #Dusk #Laravel #Telepítés (Installation) #Tesztelés (Testing)

A Laravel Dusk egy olyan szemléletes eszköz, amely egyszerűen használható böngészőbeli automatizmusok végrehajtására és tesztelésre. Mindehhez csak egy Google Chrome kiterjesztésre lesz majd csak szükségünk, és utána már futtathatjuk is a teszteseteket. A megismeréshez és a kipróbáláshoz a komplex példánkat fogjuk folytatni.
Laravel_dusk_1

Már teszteltünk korábban is, az ottani tudást ne felejtsük el: https://attila.gludovatz.hu/posts/komplex-pelda-teszteljunk-10

A Laravel Dusk legfrissebb dokumentációja itt található: https://laravel.com/docs/9.x/dusk

Amikre szükségünk van, ebben a sorrendben:

  1. Google Chrome böngésző (mivel ehhez van olyan kiterjesztés, ami szükségeltetik a Dusk-hoz)
  2. Telepítsük a Dusk-ot a projektünk Terminal-jában ezzel az utasítással: composer require --dev laravel/dusk
  3. A következő utasítással pedig a projektünkbe fogjuk telepíteni a Dusk-ot: php artisan dusk:install

Ez utóbbi utasítás létre fog hozni a projektünk tests mappájában egy browser nevű mappát, amiben rögtön megtalálható is lesz egy ExampleTest.php, meg még néhány beállítási fájl.

A következő beállítást az .env fájlunkban kell elvégeznünk. Az abban lévő APP_URL-t kell megváltoztatni olyanra, ami kiszolgálás esetén működik... ha például a php artisan serve paranccsal szoktuk futtatni a kiszolgálást, akkor ezt az APP_URL-t be kell állítani erre: http://127.0.0.1:8000/ ha mondjuk a XAMPP segítségével szeretnénk futtatni, akkor az Apache webszerver szolgálja ki, akkor pedig ez lehet az APP_URL értéke: localhost/[projekt-neve]/public , ha a felhőben (Heroku, Azure stb.) helyen futtatjuk, akkor aszerint állítsuk be ennek az APP_URL változónak az értékét. Utána indítsuk is el a php artisan serve -vel a kiszolgálást.

A tests/Browser/ExampleTest.php fájlunkat nyissuk meg és nézzük meg, hogy mi van benne: a testBasicExample függvényben láthatunk olyat, amit már a korábbi teszteknél is tapasztaltunk (vagy legalábbis hasonlót). Ez is meg szeretné látogatni a webalkalmazásunk főoldalát és ellenőrzi, hogy látható-e (a forráskódjában) a 'Laravel' szó. Futtassuk a tesztelést:

php artisan dusk

Tipp: lehetséges, hogy hibát kapunk (session not created névvel). Ekkor mindenképpen: (1) frissítsük fel a Chrome böngészőnket a legfrissebb verzióra, (2) adjuk ki ezt az utasítást: php artisan dusk:chrome-driver Utána ha újrafuttatjuk a fentebbi parancsot, már azt kell megkapnunk, hogy ...

Nálam hibát fog jelezni, mert az én főoldalamon (komplex példás alkalmazás!) nem látható a Laravel szó sehol sem.

Ha átírom a "Laravel" szó keresését "OldSchool"-ra, akkor már hiba nélkül le fog futni a kódom.

A tests mappában lévő DuskTestCase.php fájl tartalmaz néhány beállítást, mondjuk ha megnézzük a driver függvényét, akkor van benne képernyőméretre vonatkozó beállítás is, és van benne egy --headless kapcsoló is, ami a böngésző megnyitására vonatkozik teszt közben. Ha kikommentezzük ezt a sort és újra futtatjuk a php artisan dusk parancsot, akkor most már meg fogja nyitni a Google Chrome böngészőt is és láthatjuk, hogy mit csinál a tesztelés közben... most persze még ez nem annyira látványos, hiszen csak egy szót keres a forráskódban, de majd fogunk vele űrlapot is kitöltetni, ami már sokkal látványosabb lesz. Attól függően, hogy mennyire látványos / kevésbé látványos dolgot szeretnénk tesztelni a Dusk-kal, nyugodtan kapcsolgassuk (kommentezzük) ki/be ezt a --headless sort.

Ezzel a Dusk-kal a felhasználó képes lesz end-to-end tesztet csinálni (egy funkcionalitást elejétől a végéig tesztelni, mondjuk egy regisztrációs vagy belépési folyamatot, vagy a mi példánkban egy légitársaságot létre tud hozni és megnézheti, hogy bekerült-e az légitársaságok listájába, de előbb mondjuk egy utassal kezdjük tesztelni. Hozzunk létre egy új tesztet:

php artisan dusk:make PassengerTest

Ebben a fájlban automatikusan létrejön egy példateszt függvény, ezt módosíthatjuk. Adjuk meg előtte a direktívát, amiben jelezzük, hogy ő egy teszt: /** @test */

A függvény neve legyen ez: a_visitor_can_create_a_passenger

Az útvonalat változtassuk meg a főoldalról erre: /passengers/create

Majd következhet a mezők feltöltése (puskázhatunk is és megnézhetjük, hogy a böngészőben milyen mezők is látszódnak ezen az oldalon). Nálam az utas neve szöveges bemeneti mező látszódik és a repülőjárata lenyíló lista, majd következhet a mentése az utasnak, végül a teszt szeretné látni, hogy valóban bekerült-e az utaslistába a létrehozott új utas. Az egész függvény így néz ki:

/** @test */
public function a_visitor_can_create_a_passenger()
{
  $this->browse(function (Browser $browser) {
    $browser->visit('/passengers/create')
      ->type('utasneve', 'Attila') // input mező name attribútum értéke
      ->select('repulojarata')
      ->click('input[type="submit"]')
      ->assertSee('Attila');
  });
}

Ha most futtatjuk a tesztelést, akkor csak ezt az 1 fájlt teszteljük, így:

php artisan dusk tests/Browser/PassengerTest.php

Mivel a --headless kapcsolót kikommenteltük korábban, ezért már látható is, ahogy megnyílik a böngészőnk, betöltődik az URL, kitöltésre kerülnek a bemeneti mezők (a select-nek nem adtunk 2. paramétert, ezért ott egy véletlenszerűen kiválasztott repülőjárat fog kiválasztódni, majd a gombnyomást szimulálva be is jön az utaslista és bezáródik a böngészőnk... a VSCode Terminal-ban pedig látható, hogy sikeresen lefutott a teszt és az assert utasítás. Ilyen gyorsan talán nem tudtuk mi lekövetni, úgyhogy megnyithatjuk a böngészőnkben mi is az utaslistát és ellenőrizhetjük, hogy valóban bekerült-e az Attila nevű utas, és konstatálhatjuk, hogy igen.

Megjegyzés: a click() metódusban egy CSS szelektort helyeztünk el és így találja meg az oldalon jelen esetben most a Mentés gombunkat, ez teljesen jó, de ha annyira nem értenénk a CSS szelektorokhoz, akkor elhelyezhetünk a views/passengers/create.blade.php -nk mentés gombjába egy új attribútumot:

<input class="btn btn-info btn-block" type="submit" value="Mentés" dusk="save-button">

Aminek mondjuk azt a nevet adjuk, hogy "save-button". Ezután könnyebben tudunk rá hivatkozni a Dusk teszt fájlból és a click() metódusnak ezt is átadhatjuk közvetlenül így: ->click('@save-button')

Tipp, javaslat: adatok meglétének tesztelésére. De mi van, ha volt már "Attila" nevű vagy "résznevű" utasunk...? Akkor is azt fogja visszaadni, hogy "ő látja", ami esetleg félrevezethet minket, úgyhogy inkább hozzuk létre neki a tesztkörnyezetet, amiben mindig ürítsük az adatbázist. A Dusk viszont nem tudja használni a korábbi tesztelések során megismert RefreshDatabase utasítást, helyette ő azt csinálja, hogy mindig újra migrálja az adatszerkezetet, így kvázi mindig egy friss és üres adattáblákkal rendelkező adatbázissal dolgozik. Adjuk hozzá az osztályunkhoz (ne a függvényünkhöz) ezt az utasítást:

use DatabaseMigrations;


DE! Ne essünk abba a hibába, amibe én már korábban beleestem, hogy az "éles" adatbázist frissítettem majd ürítettem. Hozzuk inkább létre a tesztkörnyezetet a Dusk-nak előtte. Adjuk ki ezt az utasítást:

cp .env .env.dusk.local

Ez lemásolja az .env fájlunkat és létrehoz egy .env.dusk.local fájlt ugyanazzal a tartalommal. Viszont a "DB_DATABASE" kulcs értékét bővítsük ki (nálam ez volt: laravel_v9), így most laravel_v9_dusk lesz. Utána hozzuk is létre ezt az új adatbázist a MySQL szerverünkön. Ilyenkor a rendszer az új .env.dusk.local fájlt fogja használni a tesztelésre, utána mindig automatikusan visszaáll az eredeti .env fájlra.

Futtassuk újra a dusk-os tesztelést:

php artisan dusk tests/Browser/PassengerTest.php

És talán nem is gondoltuk volna, de hibát fogunk kapni... a hiba a ->select() metódushívással kapcsolatos. Mivel azt mondtam, hogy ha csak 1 paramétert adunk neki (repulojarata), akkor ő véletlenszerűen fog választani az értékei közül... viszont ez egy üres adatbázisnál (adattáblánál) nehezen tudna menni, hiszen még nincsenek benne repülőjáratok, ezért nem is tud közülük választani... Ezt orvosolhatjuk úgy, hogy a tesztelő függvényünk elejére beszúrjuk ezt az utasítást:

Flight::factory()->count(3)->create();

Így az utána lévő utasítás select('repulojarata') részben már 3 repülőjárat közül tud véletlenszerűen választani a teszt, ami már teljesen jó, nem fogunk hibát kapni, sikeresen le fog futni a teszt.

Próbáljunk ki még valamit: a tesztelő függvényünk utolsó sorában az assertSee() metódust írjuk át "Attila 2"-re. Nyilván ez hibát fog dobni, mivel mi csak az "Attila"-t szúrtuk be a passengers táblába. De futtassuk újra a tesztet mindenesetre.

php artisan dusk tests/Browser/PassengerTest.php

Ahogy azt vártuk, a teszt hibát is adott. Viszont nézzük meg a tests/Browser/screenshots mappában lévő képet. Ezen az látható, amin "elcsúszott" a tesztünk.

A bejegyzésben végrehajtott módosítások elérhetők ezen a Github commit linken.