Test automation
A suite your team still trusts
Most automated test suites are not abandoned because they found nothing. They are abandoned because they cried wolf — failing on a toast message, a loading overlay, a class name the UI framework invented that morning. We build regression automation whose failures mean something.
Flakiness is the product problem, not a side effect
A test that fails one run in five is worse than no test. It costs a person ten minutes to investigate, it teaches the team that red is ambiguous, and within a quarter somebody is re-running the build until it passes.
So the engineering that matters in UI automation is not writing the assertions. It is everything that makes an assertion reach its target reliably on an application that is still loading, still animating and still redrawing itself.
How it gets built
The patterns that keep a suite alive
-
Clicks that survive the interface
A shared click pipeline waits for notification toasts to clear, hides blocking overlays and modal backdrops, waits for the target to be genuinely visible, and only then clicks — falling back to a forced click when an element is not natively actionable. This absorbs an entire class of failures caused by the application's own loading behavior.
-
Locators with more than one way in
An element is declared by several strategies at once — test id, role and accessible name, visible text, class, xpath, and the frame it lives in if it is inside an iframe — chained together so whichever currently matches the DOM wins. A component library that generates its own markup stops being able to break the suite single-handed.
-
Selectors out of the specs
Selector definitions live in their own configuration files rather than inline, and the genuinely fragile ones — positional navigation tabs, generated column ids — are flagged as such where they are defined, so the next person knows what is load-bearing before they change it.
-
A failure bar above the assertions
Tests fail automatically on an unexpected browser console error, an uncaught page error, or any HTTP response of 400 or worse — with a narrow allowlist for known-broken assets. A page that technically passed while throwing errors is not a page that works.
-
Waits that match the backend
Submitting a claim, processing a payer response, distributing a payment — the result is not there when the UI stops spinning. Long-running work gets explicit synchronization and polling rather than a sleep that is too short on a bad day and wastes a minute on a good one.
-
Data as data
Scenarios that vary by customer, product, code or outcome are driven from spreadsheets rather than hard-coded into specs, so broadening coverage is a row rather than a rewrite.
Tooling
Two tracks, on purpose
-
Code-based, where a silent break is expensive
Playwright in TypeScript for the flows that move money or carry compliance risk — the ones where a regression that nobody notices is the actual danger. These justify the maintenance cost of hand-written automation, and they get page objects, resilient locators and data-driven cases.
-
AI-driven, where breadth matters more
A recorded, AI-maintained track covers the wider application far faster than hand-writing every screen would. The two are coordinated deliberately so coverage does not overlap and effort is not spent twice on the same workflow.
A suite that reads like documentation
Each automated case carries a plain-English description of the same steps, kept alongside the code, and spec files are named after the test-management case they implement. Two things follow.
The suite becomes the only documentation of those workflows that cannot quietly go stale, because it fails when it stops being true. And anyone can read what a test does without reading the test — which is what makes a QA team, rather than only its automation engineers, able to own it.
Every logical step is wrapped and named, so a failure report says which step failed in words, not a stack trace into a page object.
How an engagement runs
Highest risk first, then widen
- 01
Find what hurts if it breaks quietly
Not the longest manual script — the flow where a silent regression costs most. In billing and revenue workflows that is usually submission, posting and reconciliation.
- 02
Build the patterns on it
The first flows are where the click pipeline, the locator strategy and the data approach get established. Done properly, everything after is cheaper.
- 03
Cover the breadth
The rest of the application goes to the AI-driven track, coordinated so the two do not duplicate.
- 04
Earn reliability before automating the trigger
A suite is run on demand until its failures are trustworthy. Wiring an unreliable suite into CI only teaches a team to ignore it.
- 05
Then make it continuous
Into the build pipeline and onto a recurring schedule, so regressions surface before anyone has to go looking.
Where it has run before
We run this approach on the Practice Management applications of RXNT, a US healthcare software company, across their billing and revenue-cycle workflows — encounter creation and claim submission, insurance payment posting and distribution, statements, remittance advice, reporting and patient records.
Billing and revenue-cycle software is a good test of the method. The cost of a quiet regression there is financial and regulatory rather than cosmetic. And the screens are exactly the kind that break naive automation: generated markup, loading overlays, iframes, and backend operations that finish well after the interface says they have.
The engagement is written up in full as a case study: automation for the flows that move money.
Tell us which flow you would hate to break
That is usually the right place to start, and it is a more useful conversation than a coverage percentage.