Playwright Self-Healing Tests: How the Healer Agent Fixes Broken Tests

Playwright Self-Healing Tests: How the Healer Agent Fixes Broken Tests

Playwright's Healer agent monitors your test suite, detects selector failures, and rewrites the broken locators automatically. It is the most practical of the three Playwright agents for teams with existing test suites, because it reduces maintenance cost on day two and beyond — not just day one.

Key Takeaways

Self-healing means selector repair, not logic repair. The Healer rewrites locators that no longer match after UI changes. It cannot fix tests that break because a user flow changed, a new required field appeared, or business logic shifted.

The Healer patches the source file and re-runs to verify. Changes are written back to your .spec.ts files. Review diffs before merging — like any automated code change.

Third-party tools (Healenium, Testim, Mabl) predate the Healer and have broader healing scope. They handle more failure types but cost significantly more. The Healer is free and built-in — the right starting point for most teams.

The most common complaint about E2E test suites is not writing them. It is maintaining them. A component library update ships, button IDs change, a modal gets restructured — and suddenly twenty tests fail across the suite. Someone on the team spends a Friday afternoon hunting down selectors and patching tests instead of shipping features.

Self-healing tests exist to solve this specific problem. Playwright's Healer agent, introduced in v1.50, is the first production-quality self-healing solution built directly into the framework. This post covers how it works, where it works well, where it falls short, and how it compares to the third-party alternatives.

What Is Self-Healing in Testing?

Self-healing refers to a test runner's ability to detect that a locator has stopped working, find the element by alternative means, and update the test to use the new, stable locator — without human intervention.

The fundamental insight is that UI elements rarely disappear entirely. More often, they change their id, class, or position in the DOM. A button that was #submit-btn becomes #form-submit. A label that was Sign in becomes Log in. The element still exists and still does the same thing — the locator just stopped matching.

Self-healing detects this at runtime and fixes the pointer, not the element.

How Playwright's Healer Agent Works

The Healer agent runs after your test suite completes. It analyzes failures, determines which ones are locator-related, and attempts repairs.

Running the Healer

# Run the test suite normally first
npx playwright <span class="hljs-built_in">test

<span class="hljs-comment"># Then run the healer to repair failing tests
npx playwright agent heal --config playwright.config.ts

Or combine them in a single command:

npx playwright agent heal --run-first --config playwright.config.ts

The Healing Algorithm

When the Healer encounters a failing test, it follows this process:

  1. Classify the failure. Is this a locator not found error, a timeout, an assertion failure, or a script error? Only locator-not-found failures enter the healing pipeline.
  2. Capture the DOM snapshot. The Healer re-runs the test up to the failing step and captures the full DOM at that point.
  3. Identify the target element. Using the failing locator as a hint, it searches for elements in the DOM that match by text content, aria attributes, type, or proximity to nearby elements.
  4. Rank candidate locators. The Healer generates multiple candidate replacements and ranks them by Playwright's locator resilience guidelines: getByRole > getByLabel > getByText > getByTestId > CSS/ID selectors.
  5. Patch the test file. The highest-ranked candidate is written into the .spec.ts file, replacing the failing locator.
  6. Verify the fix. The Healer re-runs the patched test. If it passes, the change is kept. If it fails, it tries the next candidate or marks the test as needing human review.

A Concrete Example: The ID Change

Your app ships a form redesign. The designer renames component IDs for consistency. Your submit button changes:

<!-- Before -->
<button id="submit-btn" type="submit">Submit Order</button>

<!-- After -->
<button id="form-submit" type="submit">Submit Order</button>

Your test was:

test('user can submit order', async ({ page }) => {
  // ... earlier steps ...
  await page.locator('#submit-btn').click();
  await expect(page).toHaveURL('/confirmation');
});

Running the suite now produces:

Error: locator('#submit-btn') resolved to 0 elements

The Healer runs, identifies this as a locator failure, inspects the DOM at the failure point, finds a <button type="submit"> with text "Submit Order", and generates:

await page.getByRole('button', { name: 'Submit Order' }).click();

It re-runs the test. It passes. The file is updated. Your CI pipeline is green again without anyone manually touching the test.

This is not hypothetical — button and form element renaming is one of the most common causes of test suite failures after a design system update or refactor.

Multi-Step Repair

The Healer can also repair sequences where multiple selectors in a test changed. If your login form was restructured so that both the email input and the submit button have new selectors:

// Before
await page.locator('#email-input').fill('user@example.com');
await page.locator('#login-btn').click();

// After (healed)
await page.getByLabel('Email address').fill('user@example.com');
await page.getByRole('button', { name: 'Log in' }).click();

The Healer handles both in a single healing pass.

What the Healer Cannot Fix

The Healer's scope is deliberately narrow: it repairs selector drift. This is the most common failure type, but it is not the only one.

Flow Changes

If your login flow now has a two-step process — first email, then password on a separate screen — the Healer cannot restructure the test. The test has the right selectors for the old flow, but the wrong steps for the new one.

// Old test (two-step login)
await page.getByLabel('Email').fill('user@example.com');
await page.getByRole('button', { name: 'Continue' }).click();
// Test fails here — no password step in the original test

The Healer sees an assertion failure, not a locator failure. It passes the test to human review.

New Required Fields

If the checkout form now requires a phone number field that did not exist before, the Healer cannot add the missing step. The test will fail at form submission, not at a locator, and the Healer cannot generate a new test step.

Assertion Logic

If an assertion checks for a specific text value that changed — say a price that now shows as $49.99 instead of $49 — the Healer does not update assertion values. That is a logic change, not a selector change.

Comparing to Third-Party Self-Healing Tools

Before the Healer existed, teams used third-party tools for self-healing. Here is how they compare:

Feature Playwright Healer Healenium Testim Mabl
Cost Free (built-in) Open source $600+/month $2,000+/month
Failure types healed Selector drift only Selector + some flow Selector + visual Selector + visual + flow
Framework support Playwright only Selenium, Playwright Framework-agnostic Framework-agnostic
Cloud dashboard None None Yes Yes
CI integration Via CLI Via dependency Native Native
Setup complexity Minimal Moderate High High
ML-based healing Yes Yes (tree similarity) Yes Yes

Healenium

Healenium is an open-source library that adds self-healing to Selenium and Playwright via a proxy. It uses a tree-similarity algorithm to find elements that are structurally close to the original locator path. Setup requires running a Healenium backend service alongside your tests.

For teams using Selenium, Healenium is the best free option. For Playwright, the built-in Healer is simpler and does not require an additional service.

Testim

Testim uses ML to identify elements by multiple signals simultaneously — text, type, position, nearby elements. Its healing is more robust than selector-only approaches but comes at significant cost and requires adopting the Testim platform for your entire test suite.

Mabl

Mabl is a full AI-native testing platform with self-healing, visual testing, and flow detection. It handles the broadest range of failures, including visual regressions and flow changes. The cost reflects this — Mabl plans start around $2,000/month for teams.

Setting Up the Healer in CI

The most useful configuration is running healing automatically in CI after failures:

# .github/workflows/test.yml
name: E2E Tests

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Install dependencies
        run: npm ci
        
      - name: Install Playwright browsers
        run: npx playwright install --with-deps chromium
        
      - name: Run tests
        id: run-tests
        run: npx playwright test
        continue-on-error: true
        
      - name: Run Healer if tests failed
        if: steps.run-tests.outcome == 'failure'
        env:
          PLAYWRIGHT_AI_KEY: ${{ secrets.PLAYWRIGHT_AI_KEY }}
        run: npx playwright agent heal --config playwright.config.ts
        
      - name: Commit healed tests
        if: steps.run-tests.outcome == 'failure'
        run: |
          git config --global user.name 'playwright-healer[bot]'
          git config --global user.email 'healer@your-org.com'
          git add tests/
          git diff --staged --quiet || git commit -m "chore: auto-heal broken selectors"
          git push

This pattern runs tests, triggers the Healer on failure, and commits any repairs back to the branch. Your team reviews the healing commits in the PR like any other code change.

Reviewing Healer Output

Treat Healer commits like any automated code change — review them before merging. The Healer is right most of the time, but not always. Occasionally it will:

  • Pick a locator that matches multiple elements on the page
  • Choose a text-based selector for an element whose text is translated (breaking internationalization)
  • Repair a test that should have been deleted instead

A thirty-second review of the diff catches these edge cases.

HelpMeTest: Self-Healing in the Cloud

Playwright's Healer is a strong option for developer-centric teams already in the Playwright ecosystem. Its limits are its scope (selector-only) and its environment (requires local or CI Playwright setup).

HelpMeTest provides self-healing as part of its cloud-hosted test platform at $100/month flat. Tests run on a schedule in the cloud. When a selector changes, HelpMeTest detects and repairs it automatically — no CI configuration needed, no PLAYWRIGHT_AI_KEY to manage, and healing covers both selector drift and some class of flow changes via its AI layer.

Non-technical team members can review test results and healing history in the dashboard without understanding Playwright internals. For teams where QA is not exclusively a developer responsibility, this matters.

curl -fsSL https://helpmetest.com/install | bash

The Healer is the right choice if you live in the Playwright ecosystem and want to reduce your maintenance burden with minimal setup. HelpMeTest is the choice when you want persistent, scheduled, cloud-hosted healing that the whole team can see and trust.

Read more