How to run tests on every save.

•

•

Tests Running While You Type

I remember sitting in a dark apartment at 2:15 AM, staring at a terminal window while a deployment script slowly choked on a regression I should have caught three hours earlier. The problem wasn’t a lack of testing; it was the friction of the testing process. Most people will tell you that you need a massive, expensive CI/CD pipeline or a sophisticated test orchestration layer to maintain quality, but that’s usually just a way to mask a broken workflow. I learned the hard way that if your feedback loop takes more than a few seconds, you’ll eventually stop using it. I spent a lot of time figuring out how to run tests on every save without turning my laptop into a space heater or losing my flow state to a spinning progress bar.

I’m not here to sell you on a specific testing framework or some high-level DevOps philosophy. I just want to show you the practical, slightly messy ways I set up my local environment so that errors catch me before I catch them in production. We’ll look at the actual tools and the specific trade-offs involved in making your test suite feel like a natural extension of your typing, rather than a chore you avoid.

Table of Contents

Stop Guessing and Start Knowing With Unit Test Automation

Stop Guessing and Start Knowing With Unit Test Automation

The problem with the traditional “write, build, run, wait” cycle is that it’s too slow to actually change your behavior. When it takes thirty seconds to see if your change broke the payment gateway, you stop running the tests. You start relying on your gut, and my gut has failed me more times than I care to admit in a post-mortem. By implementing unit test automation that triggers the moment a file hits the disk, you move from a state of hope to a state of certainty. You aren’t just checking boxes; you are building a real-time test feedback loop that corrects your course before the mistake even leaves your editor.

I don’t care about the latest bells and whistles in developer productivity tools. I care about the cognitive load. Every time I have to manually switch contexts to a terminal to trigger a test runner, I lose a little bit of my flow. Setting up a proper file watcher configuration isn’t about being fancy; it’s about reducing the friction between an idea and its validation. When the green light stays on automatically, you can actually focus on the logic of the code rather than the mechanics of the toolchain. It turns the testing process from a chore you do at the end of the day into a continuous, quiet conversation with your codebase.

How I Learned to Stop Relying on My Own Memory

How I Learned to Stop Relying on My Own Memory

I used to think I was a “mental compiler.” I’d write a few lines of logic, mentally trace the execution path, and convince myself that the edge cases were covered. It worked fine for about six months, or at least until I was staring at a corrupted database table in a staging environment because I forgot how a specific null pointer would behave in a nested loop. The problem with relying on your own brain is that your brain is not a reliable CI/CD pipeline. It gets tired, it gets distracted by Slack notifications, and it definitely doesn’t have a perfect memory for state transitions.

This realization is what pushed me toward a more rigorous continuous testing workflow. I stopped trying to be the smartest person in the room and started relying on a real-time test feedback loop instead. By setting up a file watcher to trigger my suite the moment I hit `Cmd+S`, I moved the “discovery” phase of a bug from the pull request review—or worse, the production incident report—to the exact second the mistake was made. It’s a much more efficient way to work; it turns a potential catastrophe into a minor, almost trivial, correction.

Five ways to keep your test loop from becoming a nuisance

  • Don’t run the whole suite. If you’re running 400 integration tests every time you hit save, you’ll eventually stop hitting save out of spite. Use test watchers that only trigger the files you’ve actually touched.
  • Keep your unit tests fast. I learned the hard way that if a test takes more than a few hundred milliseconds, it’s not a unit test anymore; it’s a distraction. If it’s slow, move it to a separate, manual run.
  • Watch your CPU usage. There is nothing more frustrating than a laptop fan screaming at you while you’re trying to think, all because a background process is constantly re-indexing and re-running tests. If it’s slowing down your IDE, prune your test scope.
  • Use meaningful failure messages. A test that fails with “Expected 2 to be 3” is fine, but a test that fails with “Failed to process payment because the mock gateway timed out” saves me five minutes of staring at the debugger.
  • Accept that some things shouldn’t be automated on save. I don’t run end-to-end Selenium tests on every save. That’s a recipe for a broken workflow. Save the heavy lifting for your pre-commit hooks or the CI pipeline.

What I actually learned from this

Running tests on save isn’t about being a perfectionist; it’s about shortening the feedback loop so you catch the mistake while the context is still in your head, rather than an hour later when you’ve moved on to something else.

The goal isn’t 100% coverage—it’s reducing the cognitive load of “did I break that thing I touched ten minutes ago?” so you can actually focus on the logic instead of the side effects.

Automation is a hedge against your future self. You’re writing these checks because you know that eventually, you’ll be tired, distracted, or just plain wrong, and a simple automated gate is better than a 2 AM incident report.

The Long View

The Long View of automated testing workflows.

At the end of the day, setting up a watcher to trigger your test suite on every save isn’t about being a perfectionist or following some trendy DevOps dogma. It’s about reducing the cognitive load of your daily workflow. We’ve talked about moving away from the “manual run” cycle and building a safety net that catches the small, stupid mistakes before they ever reach a pull request. By automating this feedback loop, you stop treating testing as a separate, heavy phase of development and start treating it as a continuous conversation with your code. It turns the process from a guessing game into a predictable engineering discipline, ensuring that when you finally do push your changes, you aren’t doing so with a knot of anxiety in your stomach.

I’ve spent enough years fixing broken deployments to know that the most expensive mistakes are the ones that feel obvious in hindsight. Automating your tests is a small investment in your future self—the version of you that wants to enjoy a weekend ride on a bike instead of staring at a terminal screen. Don’t wait for the next production incident to realize your local workflow is lacking. Start small, find a tool that fits your editor, and make it part of your muscle memory. You aren’t just writing better code; you are buying back your own time and peace of mind.

Frequently Asked Questions

Won't running the full test suite on every save eventually kill my machine's performance or make my IDE unusable?

If you try to run the entire monolith suite every time you hit `Cmd+S`, you’ll definitely kill your productivity—and probably your laptop’s fan. I made that mistake early on. The trick is being selective. I use test filtering to run only the specific files I’m touching, or I use a watcher that only triggers tests related to the changed module. You don’t need the whole world verified every second; you just need the immediate context to be sane.

How do I handle the distinction between fast unit tests and those slow, annoying integration tests that take forever to spin up?

I treat them like two different tools in a workshop. If a test takes more than a few hundred milliseconds, it’s no longer a unit test; it’s an integration test. I keep my “on-save” suite strictly for the fast stuff—logic, transformations, edge cases—so I get instant feedback. The heavy hitters that spin up Docker or hit a real database? Those run on my pre-commit hook or in CI. I’d rather wait three minutes for a build than ten seconds for every single file save.

Is there a way to configure this so it only runs tests related to the specific file I just touched, rather than everything in the repo?

You absolutely can, and honestly, you should. Running the entire suite every time you hit `Cmd+S` is a quick way to turn your editor into a glorified loading screen, which kills your flow.

At what point does this become a distraction—does it actually help my flow, or am I just constantly interrupted by a failing test suite?

It becomes a distraction when your test suite takes longer to run than it takes you to type a function. If you’re staring at a progress bar for thirty seconds every time you hit `Cmd+S`, you’ve built a wall between yourself and the code. I keep my “save-to-test” loop under five seconds. If it gets slower, I split the suite or move the heavy integration tests to a background process. Flow requires feedback, not a waiting room.

Tomasz Wierzbicki

About Tomasz Wierzbicki

I am not interested in arguing about frameworks. I am interested in why the thing broke at two in the morning and what would have prevented it. Most of what I know came from being wrong in production and writing it down afterwards.