Back to News & Insights
Web Development September 7, 2026 · 5 min read

I got tired of re-recording broken tests, so I built my own testing tool

Quick disclosure so nobody feels tricked: I built and run a no-code web UI testing tool called...

I got tired of re-recording broken tests, so I built my own testing tool

Quick disclosure so nobody feels tricked: I built and run a no-code web UI testing tool called CueCast. This is the story of how it went from a personal annoyance to a shipped product — including the parts that did NOT go well.

Two sprints in a row, I spent more time fixing recorded tests than building the features they were supposed to protect. The last straw was a checkout flow test that went red because someone renamed a button. The button worked fine. The feature worked fine. The test just couldn't find it anymore. Re-recording the whole flow took the better part of an afternoon — and it broke again within the week.

Before writing any code, I listed why recorded tests die. Three reasons came up over and over: One element, one locator. Most recorders save a single CSS or XPath selector. The page hasn't even changed semantically — a new wrapper div, a reordered class list — and that one string stops matching. The test reports "failure," but the feature is fine. False alarms are worse than no alarms, because they train you to ignore red builds. The input layer lies. Many tools inject JavaScript events directly into the page. The page reacts, but not the way it reacts to a real mouse click. Hover states, focus traps, drag sequences, frameworks with their own event delegation — they all behave subtly differently. Tests pass with synthetic events and miss bugs real users hit. Failures come with no evidence. A test goes red and hands you a boolean. What did the page look like? Which step failed? Did the button move, get covered by a modal, or never render? You re-run everything locally to find out, which is the most expensive possible way to debug.

That list became my spec. Everything else was negotiable; those three were the product.

Instead of saving one selector per element, CueCast captures multiple candidates per element — structural path, accessible attributes, visible text — and replays them as a fallback chain. If the page changed and candidate #1 no longer matches, #2 and #3 still hit. The test passes, no human intervention, no re-recording.

This single decision is why replay stability is the headline feature. It's not AI magic — it's just refusing to depend on one fragile string.

Decision 2: drive the browser through the debugger protocol, not page injection.

We replay actions via the Chrome DevTools Protocol — the same channel DevTools itself uses — so clicks and typing land as trusted browser input. That means hover menus, focus behavior, and framework event handling act the way they do for a real person.

This was the hardest part of the build by far. Synthetic events are easy; trusted input is not. I burned weeks on edge cases — double-fired events, focus behaving differently after programmatic clicks, drag sequences that silently dropped — and there were moments I nearly went back to injection because "mostly right" seemed acceptable. It isn't: the whole point of replay is that it behaves like the user.

When a step fails, you get the screenshot of that exact moment, the failing step, and the page state — not a red X and a stack trace. This feature almost didn't make v1 (see below), and it turned out to be the thing users mention first.

My first version had ambitions: visual diffing, parallel cloud runs, test generators. All interesting. None finished. I cut everything that wasn't "record once, replay reliably, show me what broke" — and shipped with exactly that.

The first version another human could actually use was embarrassingly small. It was also the first version people understood in under a minute.

Lesson learned the hard way: a tool with three features that all work beats a tool with ten features that almost work. Especially in testing — trust is the entire product.

This is the part I care about most, because if my own tool doesn't survive contact with my own projects, nothing else matters.

My weekly routine: Record once, when the flow stabilizes. For a new feature, I record the happy path the moment it stops changing daily. One recording, not a maintenance project. Replay after every meaningful change. Any change that touches the UI gets a replay before I call it done. What used to be an hour of manual click-throughs across the app is now a replay I kick off and read while it runs. Read the evidence, fix once. When something goes red, the screenshot usually tells me whether it's a real bug or just a UI change before I even open the editor.

The screenshot has earned its place many times over. My favorite category of catch: the page that "looks fine" but quietly shows a stale state — a confirmation screen that renders before the backend actually committed, a list that didn't refresh, a total that didn't recalculate. Those are invisible to a pass/fail boolean and obvious in a screenshot.

The honest summary: I stopped doing the Sunday-evening manual click-through of my own app. The suite catches what I used to catch by hand — and it catches it before I've forgotten what I changed on Friday.

What I'd do differently I would have shipped the failure-evidence feature in v0 instead of v1.1. It's the feature that makes people trust red results. I underestimated how much time locators on dynamic lists would take. Elements inside virtualized lists are still the hardest case. I would have shown the product to strangers much earlier. Every week I waited was a week of feedback I didn't get.

Want to discuss this further?

Book a free strategy call with our team to see how these insights apply to your specific business goals.

Book a consultation