Self-healing locators — Healenium, Cypress cy.prompt, the Playwright healer — end the era of suites dying to every DOM refactor. They also introduce the nastiest silent failure in modern QA: the heal that makes a test pass while the feature it guarded is genuinely broken.
Tier: Core · Workflow area: Agentic test stack & self-healing
This playbook adopts self-healing deliberately: calibrate the healer against seeded changes before trusting it, scope where healing may act, and wire every heal into a review path so the wrong heal is caught before it lands.
cy.prompt (AI-assisted commands), or Playwright's healer agent (proposes diffs post-failure).Pick a pilot slice, not the whole suite. Choose 20–40 stable, strongly-asserted tests on a UI area with real churn. Wire the healer there only — global adoption before calibration is how wrong heals reach main unnoticed.
Set up the mechanism. Healenium example (Selenium/Java):
docker compose up -d # healenium backend + selector DB
WebDriver delegate = new ChromeDriver();
WebDriver driver = SelfHealingDriver.create(delegate); // heals on NoSuchElement
For Playwright, healing is not runtime magic — you run the healer agent on failures and receive diffs. That difference is a governance feature: keep it.
Calibrate with a two-change drill before trusting anything. On the staging build, apply:
id="submit-btn" to id="checkout-submit" — same behavior.Run the pilot. The correct outcome: the healer heals A's locator and the test passes; B's test may find the moved element, but the assertion on the discounted total must still fail. If B goes green, you have witnessed the wrong heal — and learned your assertions or healing scope need work before rollout. Sample calibration record:
Change A submit-rename : healed selector, test PASS -> correct heal
Change B discount-break : healed selector, total-assert FAIL -> healing scoped OK
Change B (weak variant) : healed selector, visibility-only PASS -> WRONG HEAL, blocked rollout
Scope what healing may touch. Configure the healer to act on locator resolution only — never on assertions, waits, or expected values. Any tool or prompt-based healer that "fixes" an expected value has crossed from maintenance into evidence-tampering; that capability stays off.
Route every heal to review. Healenium: enable the report/plugin so healed selectors surface per run, and export them; Playwright healer: heals are diffs by construction — open them as PRs. Either way, a heal is a proposed change with a required human decision. The companion audit-queue playbook defines the review protocol; the non-negotiable here is that no healed selector silently becomes the new baseline.
Ask the one question per heal. For each healed locator: did the app's intended behavior change here? Selector drift → accept, commit the new locator (so the heal count returns to zero). Behavior change → reject, file the bug, and mark the heal as a caught wrong-heal in your log.
Watch the heal rate as a health metric. A healthy pilot shows a burst after UI refactors and near-zero otherwise:
week 1: 14 heals (nav refactor) | 14 accepted, 0 rejected
week 4: 2 heals | 1 accepted, 1 REJECTED -> bug FE-2214 filed
A sustained high rate means locator strategy is wrong (fix with role/label locators, ARIA snapshots), not that healing is working well.
The failure mode that matters is invisible in dashboards: the suite is green, velocity is up, and a broken feature has been shipping for three weeks because a heal re-pointed the test at whatever element made it pass. Only assertion strength plus per-heal review defends against it.
cy.prompt: intent-based steps re-resolve at runtime; because there is no diff artifact, compensate with strict assertions and a periodic re-recording review of what the prompt actually did.Prompt-based healers (cy.prompt, LLM healer agents) send page structure to a model provider — on client engagements clear the tool and keep client data out of test environments it sees. Healenium's classical similarity engine runs fully self-hosted and usually clears strict policies; prefer it where model egress is blocked. If auditors require exact correspondence between versioned and executed tests, disable runtime healing entirely and use only diff-proposing healers with PR review — same benefit, cleaner trail.
Self-healing changes what a green test means: from "the app behaves as specified" to "the app behaves as specified, assuming every heal was right." Adoption is safe exactly to the degree that assumption is audited — calibrate first, scope hard, review every heal.