Using entr
as a test watcher
Published Feb 3, 2021
When I’m programming, I like to get feedback about my code as fast as possible. I like to learn about all of my bugs every time I’m “done thinking” (every time I save a file). Nowadays, LSP integrations have made it possible to get syntax and type checking on every keystroke, which is even faster than that! But everything else has to run on save.
When I discovered entr, I knew it would immediately change my workflow. I use it all the time for iterating on little one-off scripts. I edit in one terminal window and run this in another:
|
|
If it ever depends on multiple files (for larger projects or separate test data), I’ll combine it with fd like this:
|
|
But I ran into a problem using this when adding or removing files because entr (intentionally) doesn’t update the list of files by itself.
Its manual has an example for solving this (using its -d
option and a bash loop):
|
|
But I would sometimes get double-runs of my tests, which was weird and slow. So far, I’ve narrowed it down to an interaction between Neovim, ALE, Rubocop, and the write-tempfile-and-rename-into-place pattern for atomic rewrites. In other words, I have no idea.
But I do have a fix! The answer up front:
|
|
The trick turned out to be two parts:
- The
-p
option to delay execution until something changes. - Accepting the limitation of needing to wait for a file save for the first test run.
Here’s how it works:
fd .
finds all the files and directories starting from the current working directory.entr -cdp
does nothing yet because-p
makes it wait for a change.- I save a file or press Space.
entr
notices that, clears the screen (-c
), and runsmake test
.- If no directories changed (no files added or removed), goto 3.
- If a directory changed,
entr
exits with status code 2 (which is falsy in bash), sountil
’s condition has not been met. - The body of the loop runs, so the
echo
message is printed. until
loops, so goto 1.
I thought this was pretty clever, because the instructions are there when I run the command and when it “stops” on a directory change.
If you don’t like telling yourself what to do, replace the echo
command with :
(no-op) or true