Running Tests Automatically With Watchman

I'm currently working on a very small PHP library for a client and was looking for a way to automatically re-run the test suite anytime a PHP file is updated, added, or deleted.

A similar library on the Ruby side of the fence is called guard, which listens for file events and runs commands in response. I've used guard in previous projects, but I try not to pull in dependencies from other programming languages if possible in projects. Also, guard represents something that I'm trying to minimize in my development process which I'll call a "wrapper application".

"Wrapper Application"

I'm not sure if there's a better word for it, but I'm going to talk about "wrapper applications", or a library that wraps the core functionality that I'm trying to work with. In this case, it's calling a command in response to a file system change. To get to the library that is actually doing the watching, guard pulls in listen, which pulls in rb-fsevent who does the actual monitoring.

If rb-fsevent makes a breaking change (or fixes a bug, or adds new functionality) I will have to wait for the listen library and the guard library to add the new functionality. I've been burnt many times before (I'm looking at you Grunt and Gulp plugins) so I try to minimize wrappers whenever possible. The fewer moving parts, the better.

All of that said, composition of libraries is not a bad thing, just something I like to look out for. Now, back to the story.

Enter the Watchman

When trying to find applications that could fit my need without being a "wrapper", I ran into two other brew installable apps called fswatch and fsevent_watch, but their cryptic usage instructions and command line arguments led me to find Facebook's Watchman. It's open source, been out for a few years, and seemed to be able to meet my needs without requiring a "wrapper" library. In addition, it seemed to be pretty robust.

Installing is pretty straight forward thanks to brew install watchman and the introduction on their website looked straight-forward, but then things went downhill quickly.

The documentation doesn't give many example setups, so it took a few read throughs before I found how to watch files and trigger commands in response. Unfortunately,
running the test task isn't very helpful if you never see its output.

Turns out that normally triggered tasks send their output to the watchman log file that's conveniently buried deep on your system's bowels. Since I didn't want to tail a file, I kept poking around in the documentation till I found the watchman-make command. It's a convenience command that invokes a build tool in response to file changes while sending command output to your terminal. It met my needs and didn't require any complicated setup of triggers or watchers.

While digging through documentation I also found that watch-project is preferred to the deprecated watch command so that overlapping watch commands can use a common process to be easier on the operating system.

That brings the command needed for my project to:

# Run this command to monitor PHP files and run phpunit in response.
watchman-make -p 'src/**/*.php' 'tests/**/*.php' --make=vendor/bin/phpunit -t tests  

It was a bit of a journey to get everything working properly the first time, so hopefully this information will be helpful to others looking for a similar setup.

Show Comments