A locator is a product contract
The best locator describes what a user can perceive or what the product explicitly promises to automation.
Role, label, text, and deliberate test identifiers tend to survive visual rearrangement better than deep CSS paths.
When a test clicks a button by role and accessible name, it is tied to the experience the product intends to provide. When it clicks the fourth button inside a nested toolbar, it is tied to an accident of markup.
That distinction matters because redesigns should be allowed to move, group, and restyle controls without breaking unrelated behavior checks. A locator should fail when the user's meaningful path is broken, not when a div was wrapped for spacing.
Avoid encoding layout trivia
A test that depends on the third child of a wrapper is coupled to implementation details the user never sees.
When the UI changes, that kind of locator fails without proving the behavior changed. That is noise, not protection.
Common warning signs include selectors that describe grid positions, visual classes, generated component IDs, or long ancestry chains. They often pass in the beginning because the page is quiet and new. They become expensive later when the UI earns complexity.
The cost is not only maintenance. Flaky or brittle locators teach the team to distrust automation. Once the suite is seen as fragile, real failures have to fight through skepticism before they get attention.
Prefer intent before identifiers
Start with the user-facing contract: role, label, placeholder, visible text, and relationships that assistive technology also depends on. These locators improve test quality and often expose accessibility problems early.
Use explicit test identifiers when user-facing text is unstable, duplicated, translated, or insufficiently specific. They are especially useful for repeated rows, complex widgets, and workflows where the stable contract is internal to the product domain.
The useful rule is not never use data attributes. The rule is earn them. If the product cannot offer a stable accessible target and the behavior is important enough to automate, a deliberate identifier is a good engineering contract.
Name identifiers after meaning, not implementation. Prefer data-testid="submit-order" over data-testid="blue-footer-button". The first describes behavior. the second describes a design decision that may disappear.
Give automation something stable
When accessible names are not enough, agree on small test contracts such as data attributes for critical controls.
Keep them meaningful and sparse. Test identifiers should support behavior coverage, not mirror every element on the page.
A good team agreement also defines who owns locator contracts. A design, component, or journey change can require a locator update. The team must also decide whether product behavior changed.
The payoff is a suite that fails for reasons people care about. Stable locators do not make automation perfect, but they remove an entire class of avoidable noise.
That gives the team more room to focus on deeper problems: test data, environment realism, assertions, and whether the automated journey still represents meaningful risk.