Rozmaznal ma svet javascript nástrojov, kde sledovanie zmien súborov a ich polling prebehne automaticky – testy sa spustia znova v momente, keď uložíte konkrétny súbor. Táto funkcia zvyčajne prichádza out-of-the-box, obzvlášť u komplexnejších nástrojov ako Jest alebo Cypress.

Pri pokuse o to isté s PHPUnit, štandardným PHP testovacím frameworkom používaným aj Laravelom, som zistil, že automatické spúšťanie testov pri zmene súboru nie je súčasťou základnej výbavy. Našiel som viacero balíčkov, ktoré by sa dali nainštalovať cez composer, ale žiadny z nich ma nenadchol.

Som script kiddie #

Áno, záchrana v podobe kopírovania zo StackOverflow. Opäť. Mŕtvo jednoduché riešenie napísané v Bash nájdete v tejto odpovedi a vyzerá takto:

#!/bin/bash
while true; do
  FILE=$(inotifywait --exclude=".*.*sw*" --exclude="4913" ./ --format "%w%f" -e close_write) &&
  clear &&
  phpunit --color $FILE
done

Kudos užívateľovi Tango Bravo za jeho poskytnutie. Autor tiež tvrdí, že skript je kompatibilný s vim-om vďaka magickému číslu 4913, čomu, žiaľ, nerozumiem. Ako správny script-kiddie ma nezrozumenie každej časti skriptu nezastavilo v tom, aby som ho hodil do adresára Laravel projektu, urobil ho spustiteľným a spustil.

Nie je súčasťou hracej plochy: inotifywait #

Áno, čakať, že niečo bude fungovať na prvý pokus, môže byť naivné:

./watch.sh: line 3: inotifywait: command not found

Ak sledujete moje príspevky dostatočne dlho – pričom dostatočne dlho znamená niečo okolo troch mesiacov mojej blogovacej kariéry, čo je smiešne krátky čas – pravdepodobne viete ako zistiť, ktorý balíček poskytuje daný súbor. Presne to som urobil:

$ pkgfile inotifywait
extra/bash-completion
community/inotify-tools

Ťažká voľba pre používateľa zsh

sudo pacman -S inotify-tools

Skript teraz beží bez sťažností na command not found.

Plávať na vzdialené brehy #

Prvou optimalizáciou, ktorú som vykonal so spusteným sledovacím skriptom, bola zmena testovacieho príkazu. S Laravel 8 je dostupný Laravel Sail. Mal som ho už bežiaci, tak prečo ho nevyužiť?

#!/bin/bash
while true; do
  FILE=$(inotifywait --exclude=".*.*sw*" --exclude="4913" ./ --format "%w%f" -e close_write) &&
  clear &&
-  phpunit --color $FILE
+  ./vendor/bin/sail artisan test
done

Napriek tomu úprava akéhokoľvek projektového súboru hlbšie v adresárovej štruktúre nespustila testy. Na to je potrebné ísť rekurzívne:

#!/bin/bash
while true; do
  FILE=$(inotifywait --recursive --exclude=".*.*sw*" --exclude="4913" ./ --format "%w%f" -e close_write) &&
  clear &&
  ./vendor/bin/sail artisan test
done

Toto funguje rozumne dobre, ale dá sa to ešte trocha vylepšiť.

Sústreďte sa, prosím #

Jeden problém s vyššie uvedeným je, že aj samotný git status spustí testy, pretože príkaz pravdepodobne zapíše nejaký súbor do adresára .git/ (netestoval som, ale je to najpravdepodobnejší dôvod). Našťastie stačí sledovať iba niekoľko kľúčových adresárov, konkrétne app/, tests/, routes/ a prípadne resources/. Dajú sa ľahko špecifikovať:

#!/bin/bash
while true; do
  FILE=$(inotifywait --recursive --exclude=".*.*sw*" --exclude="4913" ./app ./tests  ./routes ./resources/ --format "%w%f" -e close_write) &&
  clear &&
  ./vendor/bin/sail artisan test
done

Tento skript nechávam bežať na vedľajšom monitore. Momentálne funguje dostatočne dobre. Príjemné testovanie!