Stabil Playwright end to end tesztelés várakozás nélkül!

A végtelen várakozás vége: Megbízható E2E tesztek instabilitás nélkül

Szia! Ha már neked is volt részed abban a klasszikus fejlesztői rémálomban, amikor a CI pipeline-odban az E2E tesztek hol lefutnak, hol nem, és a hiba mindig más – általában valami időzítési probléma –, akkor ez a cikk neked szól. Az end-to-end (E2E) tesztelés lényege, hogy a felhasználó szemszögéből ellenőrizze az alkalmazás működését, de gyakran pont ez a szimuláció válik a legnagyobb kihívássá. A minőségbiztosítás (quality) szempontjából alapvető fontosságú, hogy ezek a tesztek megbízhatóak legyenek, különben elveszítjük a bizalmunkat bennük.

Miért születnek az „instabil” E2E tesztek?

Az instabilitás gyökere leggyakrabban az, hogy a tesztünk túl sokat feltételez a rendszer állapotáról. Pl. fix másodpercekbe (pl. sleep(5)) kódolt várakozások, amelyek működnek egy átlagos fejlesztői gépen, de a lassabb CI környezetben vagy nagyobb adatbázis-terhelés mellett katasztrofális bukásokhoz vezetnek. A másik gyakori bűnöző: a DOM elemekre való várakozás explicit időkorlátok nélkül, amikor az alkalmazás válaszára számítunk.

Itt jön képbe a Playwright modern megközelítése. A Playwright nem csupán egy újabb automatizáló eszköz; alapvetően átgondolja, hogyan kell várakozni. Beépített, intelligens várakozási mechanizmusai vannak, amelyek *megvárják, amíg az elem tényleg kész* a interakcióra, mielőtt ráklikkelne vagy kitöltené.

A kulcs: Az intelligens várakozások (Auto-waiting)

A Playwright alapelve, hogy minden művelet (klikk, írás, stb.) automatikusan megvárja, amíg a cél elem: 1. Megjelenik a DOM-ban. 2. Nem rejtett (visible). 3. Stabil (nem animálódik éppen). 4. Kattintható (pl. nincs letiltva).

Ez elméletben szép, de hogyan néz ez ki gyakorlatban? Nézzünk egy tipikus, instabil tesztet, és hogyan javíthatjuk meg.

1. PHP Backend – Az API, amire számítunk

Tegyük fel, van egy egyszerű endpoint-unk, amely felhasználói munkamenetet hoz létre. A régi, problémás megközelítés egy explicit sleep lehetett a tesztben, hogy „biztos” legyen, a backend feldolgozta a kérést.

// backend/controllers/SessionController.php - A tesztelt endpoint
<?php
class SessionController {
    public function createSession(Request $request) {
        // ... validáció
        $userId = $request->input('user_id');
        
        // Egy összetett üzleti logika, ami időt vehet igénybe
        $sessionData = $this->sessionService->initializeComplexSession($userId);
        
        // Mentsük el, és térjünk vissza az ID-val
        $sessionId = $this->sessionRepository->persist($sessionData);
        
        return response()->json([
            'success' => true,
            'session_id' => $sessionId,
            'redirect_url' => '/dashboard'
        ]);
    }
}

A régi, naiv teszteset (mondjuk egy PHPUnit tesztben) várt volna X másodpercet, hogy a backend „befejezze”. Ehelyett a megbízható E2E teszt a Playwright segítségével a frontenden ellenőrzi a kimenetet.

2. Frontend – Ahol a teszt tényleg dolgozik

A frontend fogadja a választ, és átirányít. Itt kell biztosnak lennünk a működésben. Egy tipikus, jQuery-vel megírt siker-kezelő (amit a Playwright fog tesztelni):

// static/js/session-handler.js - A frontend kód, amit tesztelünk
$(document).ready(function() {
    $('#start-session-btn').on('click', function() {
        var $btn = $(this);
        var userId = $btn.data('user-id');
        
        // UI visszajelzés Bootstrap segítségével
        $btn.prop('disabled', true).html(
            '<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Kezdem...'
        );
        
        $.ajax({
            url: '/api/session/create',
            method: 'POST',
            data: { user_id: userId },
            success: function(response) {
                if (response.success) {
                    // A SIKERES VÁLASZ UTÁN TÖRTÉNŐ ÁTIRÁNYÍTÁS
                    // A tesztnek itt kell megvárnia, amíg ez a változás megtörténik
                    window.location.href = response.redirect_url;
                }
            },
            error: function() {
                // Hibakezelés Bootstrap alerttel
                $('#alert-container').html(
                    '<div class="alert alert-danger alert-dismissible fade show" role="alert">' +
                    'A munkamenet létrehozása sikertelen. Próbáld újra.' +
                    '<button type="button" class="btn-close" data-bs-dismiss="alert"></button>' +
                    '</div>'
                );
                $btn.prop('disabled', false).html('Munkamenet indítása');
            }
        });
    });
});

A hozzá tartozó egyszerű SCSS a jobb visszajelzésért:

// styles/session.scss
#start-session-btn {
    transition: all 0.3s ease;
    
    &:disabled {
        opacity: 0.7;
        cursor: not-allowed;
    }
}

#alert-container {
    .alert {
        // Bootstrap alapok felhasználásával
        // egyedi animáció
        animation: fadeInSlideUp 0.5s ease;
    }
}

@keyframes fadeInSlideUp {
    from { opacity: 0; transform: translateY(10px); }
    to { opacity: 1; transform: translateY(0); }
}

3. A Playwright Teszt – Ahol a varázslat történik

Most írjuk meg a megbízható Playwright tesztet, amely nem fix időket vár, hanem az oldal állapotára figyel.

// tests/session.spec.js - A Playwright teszt
const { test, expect } = require('@playwright/test');

test('Felhasználói munkamenet sikeres létrehozása és átirányítás', async ({ page }) => {
  // 1. Lépjünk az alkalmazás kezdőoldalára
  await page.goto('https://peldalink.hu');
  
  // 2. Kattintsunk a gombra, ami a session létrehozást kezdeményezi
  // A Playwright AUTOMATIKUSAN megvárja, amíg a gomb kattintható lesz
  const startButton = page.locator('#start-session-btn');
  await startButton.click();
  
  // 3. NE használjunk sleep-et! Ehelyett várjuk meg a sikeres átirányítást.
  // A `waitForURL` megvárja, amíg az oldal URL-je megváltozik a várt mintára.
  await page.waitForURL('**/dashboard');
  
  // 4. Ellenőrizzük, hogy valóban a dashboardon vagyunk-e
  // Ez a sor is vár, amíg a h1 elem megjelenik.
  const heading = page.locator('h1.dashboard-title');
  await expect(heading).toHaveText('Az Irányítópultod');
  
  // 5. Opcionális: Ellenőrizzünk egy session-specifikus elemet is
  const sessionWelcome = page.locator('.session-welcome-message');
  await expect(sessionWelcome).toBeVisible();
});

Gyakori buktatók és hogyan kerüljük el őket

1. Túl korai assert-ek: Ne azt nézd, hogy egy elem *azonnal* ott van-e a DOM-ban (isVisible()), hanem azt, hogy *végül* megjelenik-e (toBeVisible()). A Playwright expect automatikusan újrapróbálkozik egy időkereten belül. 2. Felesleges várakozások láncolása: Ha egy click() után waitForURL() van, az általában elég. Nem kell közéje tenni waitForTimeout(2000)-t „biztonság” gyanánt. 3. Hálózati kérések figyelmen kívül hagyása: A Playwright erőssége, hogy meg tudja várni a hálózati kérések befejeződését. Használd a page.waitForResponse() funkciót, ha tudod, hogy egy API hívás után változik az állapot. 4. Tesztadatok függősége: Az E2E teszteknek idempotenseknek kell lenniük. Minden teszt futása előtt hozd létre a szükséges adatokat (pl. egy tesztfelhasználót), és utána töröld. Így nem más tesztekre vagy előző futásokra hagyatkozik a siker.

Röviden összefoglalva

A megbízható E2E tesztelés kulcsa a türelem és az intelligencia, de nem a fejlesztő, hanem a tesztkeretrendszer türelme és intelligenciája. A Playwright beépített auto-waiting mechanizmusaival elkerülhetjük az instabil, időzítésen alapuló tesztjeinket. Emlékezz: a jó E2E teszt nem próbálja szimulálni az emberi várakozást másodpercekkel, hanem reagál a rendszer állapotára. Így építhetsz olyan tesztburkot, amely nem csak lefut, hanem *megbízhatóan jelzi*, ha valami *tényleg* elromlott a felhasználói élményben – és pont ez a minőségbiztosítás lényege.

A következő alkalommal, amikor egy E2E teszted „flaky” lesz, kérdezd meg magadtól: *Várok-e valamire konkrétan, vagy csak időt hagyok?* Ha a válasz az utóbbi, valószínűleg van ennél jobb megoldás.