Po úspešnom skúsenosti s mojím sledovacím skriptom pre unit a feature testy som sa rozhodol postaviť niečo podobné aj pre Laravel Dusk E2E (end-to-end) testy. Po mnohých iteráciách som však zistil, že tentokrát to bude trochu iné.
Začal som jednoducho aktualizáciou sledovača pre dusk, s nádejou na najlepší výsledok:
#!/bin/bash
php artisan dusk --ansi "$@"
fswatch --recursive ./tests/Browser ./resources \
--exclude="database.sqlite" | xargs -I% php artisan dusk --ansi "$@"
Ale objavilo sa veľa problémov. Prvým z nich bolo to, že sledovač bežal
zúrivo a takmer sa nezastavoval. Vyriešil som to spustením fswatch ., aby
som videl, čo sa skutočne deje, a následnou aktualizáciou vylúčení:
fswatch --recursive ./tests/Browser \
--exclude="database.sqlite" \
--exclude="screenshots" \
--exclude="\.log$" | xargs -I% php artisan dusk --ansi "$@"
Hlavným vinníkom boli screenshots spolu s *.log súbormi, ktoré Dusk
vytvára - tie ho dostávali do slučky. Môj editor tiež pridával niekoľko
súborov do hry, takže upravte podľa potreby. Aj po vyriešení tohto problému
však skript stále nebol dokonalý.
Ďalší problém nastal, keď beží npm run dev s vite dev serverom - testy
nemôžu bežať.
Prehliadač by nevidel nič, len prázdnu bielu stránku. Vyriešil som to
jednoducho odmietnutím spustenia testov:
<?php
// ...
abstract class DuskTestCase extends BaseTestCase {
use CreatesApplication;
use DatabaseTruncation;
protected function beforeTruncatingDatabase(): void {
file_exists('public/hot') &&
throw new Exception('❌ Vite dev server is running!');
if (!RefreshDatabaseState::$migrated) {
exec('npm run build 2>&1', $output, $returnCode);
$returnCode === 0 || throw new Exception('❌ Asset build failed');
}
// ...
}
Ďalší problém v reťazci je priamym dôsledkom predchádzajúceho. Keďže dev
server nemôže bežať, assets nie sú čerstvé medzi každým testom. Ak pridáte
nejaký atribút data-dusk=, test ho bez npm run build neuvidí.
Použitie RefreshDatabaseState::$migrated vyzerá ako pekné riešenie, ak
ide o prvý test v danej testovacej triede - rebuild sa teda spustí na
začiatku každého takého súboru. Čím viac súborov s Dusk browser testmi, tým
viac rebuildov. Stále lepšie ako buď nespúšťať rebuild automaticky, alebo
ho spúšťať pred každým testom, ale aj tak je to zbytočné.
Preto som sa rozhodol opustiť riešenie s rebuildom v PHP a namiesto toho sa zamerať na bash sledovací skript.
<?php
// ...
use Illuminate\Foundation\Testing\RefreshDatabaseState;
abstract class DuskTestCase extends BaseTestCase {
use CreatesApplication;
use DatabaseTruncation;
protected string $seeder = DatabaseSeeder::class;
protected function beforeTruncatingDatabase(): void {
file_exists('public/hot') &&
throw new Exception('❌ Vite dev server is running!');
}
}
// ...
}
Riešenie, s ktorým prišiel Claude, ma naučilo niečo nové a zdá sa, že funguje celkom efektívne:
#!/bin/bash
npm run build >/dev/null 2>&1
php artisan dusk --ansi "$@"
# Cleanup function to kill background processes on exit
cleanup() {
kill $(jobs -p) 2>/dev/null
exit
}
trap cleanup EXIT INT TERM
# Start the build watcher in background, suppress all output
fswatch --recursive ./resources | xargs -I% npm run build >/dev/null 2>&1 &
# Run the dusk watcher in foreground with full colored output
fswatch --recursive ./tests/Browser \
--exclude="database.sqlite" \
--exclude="screenshots" \
--exclude="\.log$" | xargs -I% php artisan dusk --ansi "$@"
Za predpokladu, že aplikácia používa Blade alebo Inertia pre frontend, uvedený skript robí viacero vecí:
- sleduje priečinok
resources/, recompiluje iba pri zmenách na FE - zabraňuje tomu, aby výstup buildu znečisťoval výstup testov
- znovu spúšťa Dusk testy iba keď sa zmenia ich súbory
- správne zobrazuje výsledky testov
- ukončí oba sledovače pri ukončení skriptu
Užite si to!