Q27 of 37 · Selenium
Walk through your strategy for stable selectors that survive UI refactors.
Short answer
Short answer: Push for `data-test` (or similar) attributes on every interactive element. Treat them as test API — versioned, code-reviewed, never removed silently. Lint for forbidden patterns (positional xpath, generated class names). Track 'what broke and why' to keep the policy tight.
Detail
Stable selectors are a cultural problem more than a technical one. The technical patterns are simple; the discipline to maintain them is the real lift.
1. The selector hierarchy (in priority order):
[data-test=...]— test-only attribute, free of design concerns.[role=...][aria-label=...]— semantic, often stable across visual refactors.- Stable
name/ form attributes. - Visible text via XPath (
//button[normalize-space()='Sign in']). - Generated ids — only with starts-with anchors and as a last resort.
2. Treat data-test as a test API. The argument I make to dev teams: "If you'd remove a public method without a deprecation, you'd break callers. data-test attributes are the public API of your UI for QA. Treat them with the same care."
Concretely:
- Code review checks: PRs that touch components without a data-test on new buttons get flagged.
- Renames are a coordinated change with QA, not a side-effect of styling refactors.
- ESLint rule (or equivalent for your stack) requiring data-test on
<button>and<a>.
3. Lint your test suite for fragile patterns:
- Positional xpath (
(//tr)[3]). - Hashed CSS-in-JS classes (
.css-1q2w3e4). - Brittle text matching that includes punctuation likely to change ("Sign in to your account.").
A pre-commit hook or CI grep that fails on these patterns is cheap and catches drift early.
4. Track failures by cause. Keep a small spreadsheet (or annotation in your bug tracker) of every test fix. Tag whether the cause was: a UI bug, a stale locator, a timing issue, or test logic. After a quarter, the mode is usually obvious — and the data lets you push back when leadership asks "why are tests still flaky?"
5. Pair-program the first round of pages with frontend engineers, especially on a new project. They learn what makes selectors fragile; you learn the underlying component structure. The selector strategy that emerges is mutual.
The interview signal: framing this as a cross-team policy with measurable inputs (lint, code review) and outputs (failure-cause tracking) — not as a "use data-test, the end."