Next-Gen App & Browser Testing Cloud
Trusted by 2 Mn+ QAs & Devs to accelerate their release cycles

Intent-based testing binds a test to the outcome it must prove instead of the DOM path that currently produces it. Here is the mechanism, a measured comparison of which locators survive a refactor, and the failure mode that makes these tests pass when they should not.

Samyak Goyal
Author

Anubhav Singhmaar
Reviewer
Last Updated on: August 26, 2026
A checkout suite goes red on Monday. Checkout works fine. Over the weekend someone renamed a CSS class, the selector stopped resolving, and forty tests failed for a reason that has nothing to do with whether a customer can buy anything.
That failure is not a bug in the test. It is a consequence of what the test was bound to. A script asserts on a path through the DOM, so it reports on the stability of that path, not on the behavior you actually care about. Intent-based testing changes the binding.
TL;DR
Intent-based testing states the outcome a test must prove and delegates the route to an agent. The test says a user can complete checkout and receive a confirmation. It does not say which button carries which id, or how many divs sit between the form and the submit control.
The reason this matters now is a change in where code comes from. Google's DORA research finds that 90% of survey respondents report using AI at work, and that AI adoption continues to have a negative relationship with software delivery stability. The 2025 DORA report announcement names the control that decides which way it goes: without robust control systems, "like strong automated testing, mature version control practices, and fast feedback loops, an increase in change volume leads to instability."
That is the pressure. Code volume is rising, the UI churns faster, and a suite whose tests are pinned to DOM paths gets more expensive exactly when it needs to get cheaper. The practical question is what a test should be attached to so it survives.
What separates the two approaches is the input format far less than what the test breaks on.
| Dimension | Script-based test | Intent-based test |
|---|---|---|
| What it is bound to | A stored selector and a fixed ordered path through the DOM. | An outcome stated as observable evidence, resolved fresh on each run. |
| What breaks it | Any DOM change touching the path, including changes that preserve behavior. | A change in the behavior itself, or an outcome the agent cannot evidence. |
| Failure meaning | Ambiguous. A red test may mean a regression or a rename. | Narrower. The stated outcome was not met by the evidence required. |
| Dominant risk | False failures, which are noisy and get triaged. | False passes, which are silent and do not get triaged. |
| Who can author | Whoever can write and maintain framework code. | Anyone who can state the outcome precisely enough to be checked. |
Mainstream frameworks already moved partway here, which is the part most write-ups on this topic miss. The Playwright locators documentation states that "CSS and XPath are not recommended as the DOM can often change leading to non resilient tests," and recommends role-based locators because a role "reflects how users and assistive technology perceive the page."
A role locator is an intent-flavored locator. It names what the control is for rather than where it sits. Intent-based testing extends that idea from the element up to the whole assertion. If you are still writing selector-first suites, the Playwright tutorial covers the locator strategies this builds on.
Between the sentence you write and the browser action there are four steps, and knowing them is what lets you debug a run that goes wrong.
Step four is where most of the engineering argument lives, and it is worth being precise about it. The model is not deterministic. The contract can be. A language model reasoning about a page may take a different internal route on each run, so the click path is not guaranteed to be identical. What stays fixed is the rule for granting a pass: the agent decides how to reach an element, and does not get to decide on its own that the test passed. The KaneAI command guide documents the command vocabulary this resolves into.
Those four steps collapse into three layers once a test is running, and separating them is the fastest way to triage a failure. A red run means one specific layer disagreed with you, and each layer fails for a different reason.
| Layer | What it holds | What a failure here means |
|---|---|---|
| Intent | The outcome you stated, in the words you stated it. | The instruction was ambiguous or described behavior the product never had. Fix the sentence, not the app. |
| Resolution | The mapping from that intent to a concrete element on the live page. | The target was missing or genuinely ambiguous, with two plausible matches on screen. Disambiguate by naming the region. |
| Assertion | The evidence required before a pass is granted. | The real one. The flow ran and the expected state did not appear, which is the regression you wrote the test to catch. |
The layer split also explains how mature implementations keep model latency out of the common path. Resolve the intent once, cache the element it resolved to, and replay the cached target on later runs; when the cached target stops matching, fall back to resolving again and heal it. Normal runs then cost about what a scripted run costs, and the model is only invoked at the moment something actually moved.
The claim that semantic resolution survives UI change is repeated constantly and rarely measured. So we measured it.
Method. We loaded the Simple Form Demo page on the TestMu AI Selenium Playground in a real Chrome session on TestMu AI Browser Cloud and resolved one target control, the "Get Checked Value" button, three ways: by CSS id, by absolute XPath derived from the live DOM, and by role plus accessible name. We then applied a routine front-end refactor to the live page, renaming the id from showInput to submit-message-cta, replacing the class list, and wrapping the button in a new div. Then we resolved all three again. The refactor was applied deliberately in-page so both passes ran against the same page in the same session; it is a controlled simulation of a rename, not an observed production incident.
The three locators, exactly as run:
await page.goto('https://www.testmuai.com/selenium-playground/simple-form-demo');
// 1. Implementation-coupled: bound to an id attribute
await page.locator('#showInput').first().waitFor({ state: 'attached', timeout: 5000 });
// 2. Structure-coupled: bound to a position in the DOM tree
const xpath = '/html[1]/body[1]/div[1]/div[1]/main[1]/div[1]/section[2]' +
'/div[1]/div[1]/div[1]/div[1]/div[2]/div[1]/div[1]/button[1]';
await page.locator(`xpath=${xpath}`).first().waitFor({ state: 'attached', timeout: 5000 });
// 3. Intent-coupled: bound to what the control is for
await page.getByRole('button', { name: 'Get Checked Value' })
.first().waitFor({ state: 'attached', timeout: 5000 });Results from the run, with resolution time measured to the point the locator attached:
| Locator strategy | Before refactor | After refactor |
|---|---|---|
| CSS id | Resolved, 264 ms | Failed, timed out at 5,000 ms |
| Absolute XPath | Resolved, 150 ms | Failed, timed out at 5,000 ms |
| Role and accessible name | Resolved, 113 ms | Resolved, 304 ms |
Three findings worth carrying forward. The rename alone was enough to break both implementation-coupled strategies, and neither failure had anything to do with whether the button worked. The role locator kept resolving because the button's purpose did not change, only its markup. And the intent-coupled lookup was not slower in the healthy case, resolving in 113 ms against 264 ms for the id selector, so the cost argument against semantic resolution does not hold at the element level.
One caveat, stated plainly: this measures element resolution, not a full agent run. An agent reasoning about a page adds model latency that a single locator call does not. What the test isolates is the binding, and the binding is the part that decided whether the test survived.
Script-based suites fail loudly and waste your time. Intent-based suites can pass quietly and waste your confidence, which is worse, because nobody triages a green run.
There is now measured evidence for how wide the gap between "the test ran" and "the test would catch a bug" can get. In Benchmarking LLMs for Unit Test Generation from Real-World Functions, Huang, Zhang, Harman and colleagues evaluated model-generated tests and reported that on the TestEval benchmark they reached 92.18% statement coverage but only a 49.69% mutation score. On their harder ULT benchmark, built from real-world Python functions, the average mutation score fell to 40.21%.
Mutation score measures whether a test actually detects deliberately introduced faults, which is what makes the pairing Huang and colleagues report so pointed: near-total statement coverage sitting beside a mutation score roughly half as large describes tests that execute the code thoroughly and notice very little about it. Their study covers generated unit tests rather than browser intents, and the mechanism transfers, because when the thing being generated is the check itself, running is not the same as verifying.
In practice the false pass has one common cause, and it is the objective, not the model. An instruction like check that the page works defines no pass condition. The agent loads the page, observes it, finds nothing that contradicts a vague goal, and reports a pass that carries no information. The same run with a named piece of evidence attached would have had something to fail against.
A usable intent combines three things: an action to perform, an assertion that can be falsified, and an extraction when a downstream step needs the value. Assertions are the load-bearing part, because an intent with no assertion cannot fail for the right reason.
# Weak: no defined pass condition, so a pass means nothing
kane-cli run "go to the checkout page and check that it works"
# Strong: named evidence the run must produce
kane-cli run "go to https://ecommerce-playground.lambdatest.io/,
search for 'iPhone',
add the first result to the cart,
open the cart,
assert the cart contains 'iPhone',
assert no error message is visible,
store the cart total as 'cart_total'"Assertion styles that give a run something concrete to fail against:
One phrasing trap is worth calling out because it fails silently. Asking an agent to "tell me the price" is observational, and the value may appear in a summary without ever being captured for a later step to use. Naming the variable explicitly, as in store the price as a named value, is what persists it into the run output where CI can parse it.
Where the intent then lives is a separate decision from how it is phrased, and it decides whether the suite is reviewable. A one-off objective typed at a terminal is fine for exploration and leaves nothing behind. Test.md, the markdown-based framework in Kane CLI, persists the same plain-English objectives as step-level headings in a file, with front matter for environment variables and an import mechanism for shared flows like login. That form is worth reaching for as soon as a test matters, because a markdown file is reviewable in a pull request and a typed command is not.
Note: KaneAI turns a plain-English intent into an executable test, resolves elements semantically instead of by stored selector, and re-anchors steps when the UI shifts so maintenance becomes a review step rather than a rewrite. Try TestMu AI free!
Every vendor page on this topic argues for converting everything. That is the wrong shape of advice, because some tests get worse under semantic resolution. Use this rule: convert the test when the outcome is the point, and keep the script when the path is the point.
| Test type | Convert to intent? | Why |
|---|---|---|
| End-to-end user journeys | Yes | The outcome is the behavior, and these are the tests that break most often on cosmetic UI change. |
| Smoke and regression suites | Yes | High churn, low complexity per test, and the pass condition is easy to state as evidence. |
| Performance benchmarks | No | Model latency in the run loop contaminates the measurement you are trying to take. |
| Unit and API contract tests | No | There is no UI to resolve semantically, and these are already fast and deterministic. |
| Very long single flows | Split first | Agent reliability degrades as step count grows, so a 30-step objective should become three shorter ones. |
The step-count limit is a genuine constraint rather than a caveat to wave past. An agent's reasoning loop drifts as an objective grows, and past roughly fifteen steps reliability starts dropping. Splitting a long journey into shorter objectives that each carry their own assertions is the fix, and it also makes a failure point to a smaller region of the flow.
Tests that fail intermittently deserve their own decision. Converting a flaky selector-bound test to intent may remove the flakiness if the cause was selector churn, and will not touch it if the cause is a race condition or test data. Diagnose before converting, because an intent-based test that inherits a real race will still be flaky and will now be harder to read. Our guide to flaky tests covers separating those causes.
Nobody converts a mature suite in one pass, and nothing about this approach requires it. A practical sequence that keeps the existing suite authoritative throughout:
Step four is the one teams skip and the one that matters most. Every other step tells you the test can pass. Only a deliberate break tells you it can fail, which is the only property that makes a green run mean anything. For terminal-driven and CI-driven runs the same objectives execute through Kane CLI, which reports per-run outcomes your pipeline can parse.
Start with the single test your team has repaired most often this quarter. Rewrite it as an outcome with at least one positive assertion and one negative assertion, run it alongside the original against the same build, then break the behavior on purpose and confirm it goes red. That one exercise teaches more about intent-based testing than any amount of reading, and it costs an afternoon.
The measurement in this article is the argument in miniature. A rename broke both selector-bound strategies and left the behavior untouched, while the locator bound to what the control was for kept resolving. Tests attached to purpose survive changes that tests attached to structure do not.
To author from intent and keep the framework code, KaneAI generates tests from natural-language prompts, requirement documents, and pull requests, re-anchors steps when the UI changes, and exports to Selenium, Playwright, Cypress, or Appium. The getting started with KaneAI documentation walks through the first test end to end. If you want to see how intent-shaped authoring reads before committing to it, our write-up on natural language test automation covers the authoring layer, and self-healing test automation covers what happens after a locator moves.
Author
Samyak Goyal is a Senior Member of Technical Staff at TestMu AI engineering Kane CLI, the command-line tool that runs browser automation from the terminal, where a flow described in natural language executes in a real Chrome browser and returns pass or fail with shareable proof. He is a backend engineer with 4+ years of experience, previously an SDE at Innovaccer, where he built APIs, introduced Kafka, and cut deployment from weeks to hours. Samyak also builds multi-agent systems, skill-orchestration frameworks, and a personal copilot that indexes 200+ microservice repositories.
Reviewer
Anubhav Singhmaar is an AI Product Manager at TestMu AI driving Kane CLI, the command-line tool that brings browser automation to the terminal, turning natural-language flows into runs in a real Chrome browser that return pass or fail with shareable proof. He owns the roadmap and prioritization and works with engineering to ship developer-facing features. Before TestMu AI, he spent over four years at Sprinklr owning enterprise voice AI across APAC and EMEA. A mechanical engineer turned product manager, he grounds guidance in real QA workflows.
Did you find this page helpful?
More Related Blogs
TestMu AI forEnterprise
Get access to solutions built on Enterprise
grade security, privacy, & compliance