wackystudio/laravel-test-watcher
A Laravel package that watches your project files and automatically reruns your tests when code changes, providing fast feedback and streamlining test-driven development. Simple to set up for local workflows and continuous testing.
Install as a dev dependency so it doesn't ship to production:
composer require wackystudio/laravel-test-watcher --dev
Publish the config (needed if the package ships a config/test-watcher.php):
php artisan vendor:publish --provider="WackyStudio\TestWatcher\TestWatcherServiceProvider"
Look first at the package's README.md and config/test-watcher.php — for a package this small there's usually one artisan command and one config file, and the README documents both. Confirm the artisan command is registered with:
php artisan list | grep -i watch
The first useful thing to do is drop into a TDD loop: open a test file, run the watcher once so it boots and scans, then edit a test or a class and watch it re-run. A typical first command looks like:
php artisan test:watch
If that command doesn't exist, check the README — the namespace/handler name is the only real unknown, and once you have it the rest is config-driven.
Config-driven watching. Expect a config array like paths, exclude, phpunit / test_command, and possibly notify. Point paths at app/, src/, tests/, and routes/ and exclude storage/, vendor/, node_modules/, and bootstrap/cache/ so the watcher isn't reacting to logs and compiled views.
Override the test command per project. If you use Pest, Paratest, or a custom PHPUnit binary, set the test command in the config rather than expecting the package to auto-detect it. This is the single most common adjustment. A config value approximating:
'test_command' => 'vendor/bin/pest',
// or 'vendor/bin/phpunit --colors=always'
Filter during focused work. When debugging one failing test, pass the filter/suite through to the underlying command (either via config or CLI args, depending on what the package supports):
php artisan test:watch --filter=UserRegistrationTest
Even if the watcher doesn't expose a --filter option directly, editing the test_command in the config to include --filter= gets you the same result.
Pair with a queue worker / Vite in separate terminals. The watcher occupies a tab. Keep node/vite running in another and a queue worker in a third — the watcher is only for the test feedback loop, not a replacement for your other dev processes.
CI parity check. Don't let the watcher become a crutch. Before pushing, run the full suite the way CI does (php artisan test or vendor/bin/phpunit) — the watcher may only run a subset depending on how you configured paths/filters.
Editor integration. Because the package just shells out to PHPUnit and watches files, wire it to a keybinding in your editor (e.g., "run tests in watch mode" task). The package doesn't care how it's launched.
composer require resolves cleanly against your composer.json; if there are constraints like "laravel/framework": "^7.0 || ^8.0" you'll need --ignore-platform-reqs (don't) or an alternative (see below). For a fresh project, spatie/phpunit-watcher, nunomaduro/pest's built-in watcher, or a simple entr/watchexec one-liner is safer.phpunit-watcher). On large monorepos this burns CPU even when idle. If you see a constant 15–30% CPU floor, reduce watched paths or switch to a inotify-based tool.php artisan config:cache in local dev (rare but it happens after pulling a config that runs config:cache in a deploy script), your changes to test-watcher.php are ignored. Run php artisan config:clear when debugging "my config change did nothing".--dev, the service provider is registered normally but be sure composer dump-autoload ran. If php artisan lists the command but it errors, the underlying phpunit binary path is almost always the culprit — use vendor/bin/phpunit explicitly, not phpunit.system('clear') can swallow output on Windows or in non-TTY terminals (e.g., when run inside an IDE task runner). If you see a blank screen with no test output, disable the clear/notification option in the config.php-cs-fixer pass before tests), the pragmatic path is a small shell script you point test_command at — don't try to extend the watcher itself.require-dev and not require before shipping.inotify watching the wrong inode, or (c) polling interval too coarse. Test with touch app/Models/User.php in a terminal with no editor involved — that isolates the watcher from editor weirdness.How can I help you explore Laravel packages today?