Trying to do the same thing with PHPUnit, the standard PHP testing framework used by Laravel too, I found automatic test running on file change not included as a first-class citizen. I have found multiple packages that could be installed by composer, buy all of them did not appeal to me.
I am a script kiddie
Yes, StackOverflow copy-paste to the rescue. Again. The dead-simple solution written in Bash could be found in this answer and looks like this:
#!/bin/bash while true; do FILE=$(inotifywait --exclude=".*.*sw*" --exclude="4913" ./ --format "%w%f" -e close_write) && clear && phpunit --color $FILE done
Kudos for the user
Tango Bravo for
providing it. The author also claims the script is vim compatible, due to
the magic number
4913 which I do not understand unfortunately. As a
proper script-kiddie, not understanding every part of the script did not
prevent me putting the script into the Laravel project directory, made it
executable and run it.
Not part of the playground: inotifywait
Yeah, expecting something to run on the first time might be foolish:
./watch.sh: line 3: inotifywait: command not found
If you follow my posts for long enough, where long enough means something around three months worth of my blogging career, which is hilariously short time, you probably know how to determine which package provides the file. I did exactly that:
$ pkgfile inotifywait extra/bash-completion community/inotify-tools
A tough choice for a
sudo pacman -S inotify-tools
The script now runs without
command not found complains.
Sail to the distant shores
The first optimization that I did with the running watch script was to change the test command. With the Laravel 8, the Laravel Sail is available. I had it running already, so why not use it?
#!/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
Still, editing any project file deeper in the directory structure did not trigger the test run. We need to go recursive for that:
#!/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
This works reasonably well, but it can get a little bit better still.
One problem with the above is that a mere
git status triggers the test
run as the command probably writes some file into the
.git/ directory (I
did not test, but it is the most likely reason). Luckily, we just need a
monitor a few key directories, namely
resources/. They can be specified easily:
#!/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
I keep this script running on the side monitor. Currently it works well enough. Happy testing!