L6 · AI as your instrument
L6Go deeper4 min read

Self-healing locators: what breaks and when

The most oversold idea in test automation and not entirely worthless. Understand what it actually does, the failure mode where it happily heals past a genuine bug, and when a stable test id is simply the better answer.

A locator is how a test finds an element on a page: a CSS selector, a test id, a role and a name.

Self-healing means the tool looks for the element another way when the locator stops matching. It uses nearby text, position, role, or a stored snapshot of the element. If a good candidate turns up, the test carries on and the locator is repaired.

It is the most oversold idea in test automation, and not worthless. The distinction is simple.

Self-healing is genuinely useful when the element is the same and its handle changed. It is dangerous when the page changed on purpose, because it will find something that looks close enough and let a real defect pass.

The terms you will hear

  • Locator, or selector. The expression that finds an element.
  • Test id. An attribute added for testing, such as data-testid, which product changes rarely touch.
  • Semantic locator. Finding by role and accessible name. Stable and accessible by construction.
  • Healing. Substituting an alternative locator at run time when the original fails.
  • Confidence score. How sure the tool is about the substitute. The number to gate on.
  • Drift. Small accumulated differences between what the test expects and what the page is.

What it is actually good at

  • A rename. .btn-primary becomes .button-primary. Same button, same place, same text. Healing here saves a tedious afternoon.
  • A framework upgrade that regenerates class names wholesale.
  • A wrapper element appearing or disappearing, breaking a brittle descendant chain.
  • A large legacy suite you inherited, where the alternative is 400 failing tests and no time.

Where it hurts

  • The element moved for a reason. The pay button moved into a confirmation step. Healing finds the old-looking button somewhere else and the test passes, so nobody notices the flow changed.
  • Two similar elements. Two "Apply" buttons, one for a discount code and one for a gift card. Healing picks the wrong one and the test now checks the wrong feature, silently, forever.
  • It hides accessibility problems. A button with no accessible name is a real defect. Healing finds it by position and the defect survives.
  • The assertion. Healing a locator inside an assertion is how a check quietly starts examining a different element.

How to use it without getting hurt

  1. Fix the locator strategy first. Test ids and role-based locators remove most healing events entirely. This is the real fix, and healing is a patch over its absence.
  2. Treat every heal as a proposed change. Collect them, review weekly, commit the right ones. It is the same review discipline as reading an agent's diff.
  3. Gate on confidence. Accept high-confidence heals in the run, and fail anything below the threshold so a person looks.
  4. Never heal assertions. Locate leniently if you must, assert strictly. That split keeps the check honest.
  5. Never heal on money paths. Payment, refunds, anything irreversible. Let those fail loudly, which is what risk ranking says about consequence.
  6. Watch the heal rate. A rising rate is not a success story. It means the page and the suite are drifting apart, and the suite is being quietly rewritten by a tool.
  7. Diff the healed locator against the intent. "It found a button labelled Apply" is not enough. Which Apply?

A heal is an edit to your test made by a tool, at run time, with nobody watching. Review it like any other edit or accept that your suite is now partly written by something with no idea what it is checking.

A worked week

For example, here is a week of heals from a suite of 260 browser tests, reviewed on the Friday.

heal-review.txt
WEEK  4 to 8 September      HEALS PROPOSED  23

ACCEPTED (17, all committed as locator fixes)
  11  .btn-primary -> [data-testid="submit"]      class rename in a
                                                  design system upgrade
   4  wrapper div added, descendant chain broken   same element
   2  aria-label spelling corrected                same element

REJECTED (6, and this is why the review exists)
   2  "Apply" button on checkout
      healed from the gift-card Apply to the discount-code Apply.
      both are labelled Apply, and the test has been checking the
      wrong feature since Tuesday.            REAL PROBLEM, fixed with
                                              a test id on each
   1  pay button
      moved into a new confirmation step on purpose. healing found the
      old-style button on the summary page, so the test passed and
      never visited the new step.             DEFECT HIDDEN, test rewritten
   2  found by position after the accessible name was removed
      the missing accessible name is an accessibility defect.
                                              raised as WB-1902
   1  confidence 0.41, matched a different modal entirely
                                              would have been caught by a
                                              threshold, which we then set

CHANGES MADE
  set the confidence threshold to 0.85, fail below it
  disabled healing on the payments spec entirely
  added test ids to the two Apply buttons
  heal rate the following week: 6, all accepted

Twenty-three heals, seventeen genuinely helpful, and six that were either hiding a defect or checking the wrong thing. The tool paid for itself and it also needed the Friday.

How to show you know it

  • A heal review log. Accepted and rejected, with reasons. Very few teams do this, and it is the whole practice.
  • A hidden defect you found in a heal. The pay-button case is the canonical example.
  • A locator strategy change. Reducing the heal rate by adding test ids is the durable fix, and the numbers make the argument.
  • A disabled path. "Healing is off for payments." One line, and it shows you rank by consequence.

Questions

Is self-healing worth turning on at all?

On a large legacy suite with brittle selectors, yes, with a review step. On a new suite, spend the same effort on test ids and semantic locators and you will barely need it.

Does it fix flaky tests?

No, and it can mask them. Most flakiness is timing and state rather than locators, which is a different investigation entirely, covered in flaky test detection.

What confidence threshold should I use?

Start high, around 0.85, and tune from the rejected heals. The exact number matters less than having one at all, because without it every guess is accepted.

Who reviews the heals?

Whoever owns the suite, once a week, in fifteen minutes. If nobody owns it, that is the finding, because an unowned suite is being rewritten by a tool with no view on what matters.