Healing Engine

The Healing Engine is the core innovation of this framework. It automatically detects and repairs broken selectors in your Page Objects when your application's DOM changes, eliminating the need for manual selector maintenance.

How It Works

The healing process operates in three distinct phases:

Phase 1: Learn (Selector Registry)

During successful test runs, the framework records multiple locator strategies for each element into a registry file (agents/selectors.registry.json).

What gets recorded:

  • Primary selector (as written in your Page Object)
  • Alternative strategies:
    • data-test attributes
    • Role-based locators (getByRole)
    • Text-based locators (getByText)
    • CSS selectors with variations
    • XPath fallbacks

Example registry entry:

{
  "LoginPage.EmailInput": {
    "primary": "#user-name",
    "alternatives": [
      "[data-test='email-input']",
      "getByRole('textbox', { name: 'Email' })",
      "getByPlaceholder('Enter your email')",
      ".email-field",
      "//input[@type='email']"
    ],
    "lastVerified": "2025-01-15T10:30:00Z"
  }
}

Phase 2: Failure Detection

When a test fails due to a selector issue, the Healer:

  1. Parses test output to identify failing scenarios
  2. Extracts the failing Page Object and property name
  3. Captures the current DOM state from test artifacts
  4. Compares the expected selector against the actual DOM

Detection logic:

// Simplified example
var failure = ParseTestOutput(testResults);
var brokenSelector = failure.PageObject + "." + failure.Property;
var currentDOM = await CaptureDOMState(failure.Scenario);
var registry = LoadSelectorRegistry();

Phase 3: Auto-Repair

Using Roslyn code analysis, the Healer:

  1. Loads the selector registry for the failing element
  2. Tests each alternative strategy against the current DOM
  3. Finds the first working alternative
  4. Rewrites the Page Object property using Roslyn
  5. Rebuilds the project
  6. Re-runs the affected tests

Repair process:

// Simplified example
var workingSelector = FindWorkingAlternative(brokenSelector, registry, currentDOM);
var pageObjectFile = LocatePageObjectFile(failure.PageObject);
var sourceCode = File.ReadAllText(pageObjectFile);

// Use Roslyn to rewrite the property
var updatedCode = RewriteProperty(sourceCode, failure.Property, workingSelector);
File.WriteAllText(pageObjectFile, updatedCode);

// Rebuild and re-run
await RebuildProject();
await RerunTests(failure.Scenario);

Using the Healing Engine

Initial Setup: Learn Phase

Before healing can work, you must build the selector registry. Run this on a green test suite:

dotnet run --project ./Agents/Agents.csproj -- learn \ --test ./Tests.E2E/Tests.E2E.csproj \ --out ./agents/selectors.registry.json

What happens:

  • Framework executes all tests
  • For each Page Object property accessed during tests, multiple selector strategies are captured
  • Strategies are tested and ranked by reliability
  • Registry is written to agents/selectors.registry.json
Update the registry
Re-run the learn command periodically (e.g., after major UI changes) to refresh the registry with new selector strategies.

Simulating a Failure

To test the healing mechanism:

  1. Intentionally break a selector in a Page Object:
// Before (working)
private ILocator EmailInput => Page.Locator("#user-name");

// After (broken - changed selector)
private ILocator EmailInput => Page.Locator("#first");
  1. Run tests to see the failure:
dotnet test ./Tests.E2E/Tests.E2E.csproj

You'll see test failures indicating the selector cannot be found.

Healing the Tests

Run the Healer to auto-repair:

dotnet run --project ./Agents/Agents.csproj -- heal \ --test ./Tests.E2E/Tests.E2E.csproj

What the Healer does:

  1. Analyses test output to find selector failures
  2. Loads agents/selectors.registry.json
  3. For each broken selector:
    • Tests alternatives from the registry
    • Finds the first working strategy
    • Rewrites the Page Object property
  4. Rebuilds the project
  5. Re-runs the previously failing tests

Output example:

[Healer] Detected 2 selector failures:
  - LoginPage.EmailInput: #first → #user-name (repaired)
  - CheckoutPage.FirstNameInput: #first → [data-test='first-name'] (repaired)

[Healer] Rebuilding project...
[Healer] Re-running 3 affected scenarios...
[Healer] All tests passing ✓

Selector Registry Format

The registry is a JSON file mapping Page Object properties to selector strategies:

{
  "PageObjectName.PropertyName": {
    "primary": "original-selector",
    "alternatives": [
      "alternative-1",
      "alternative-2",
      "alternative-3"
    ],
    "lastVerified": "ISO-8601-timestamp",
    "successRate": 0.95
  }
}

Best Practices

1. Keep Registry Updated

Run the learn command regularly, especially after:

  • Major UI refactoring
  • Adding new Page Objects
  • Significant application updates
# Weekly or after major changes dotnet run --project ./Agents/Agents.csproj -- learn \ --test ./Tests.E2E/Tests.E2E.csproj \ --out ./agents/selectors.registry.json

2. Use Stable Selectors

While the Healer can repair selectors, prefer stable strategies:

Good:

// data-test attributes (most stable)
Page.Locator("[data-test='email-input']")

// Role-based (semantic)
Page.GetByRole(AriaRole.Textbox, new() { Name = "Email" })

Avoid:

// Fragile CSS (breaks with styling changes)
Page.Locator(".form-group > div:nth-child(2) > input")

// XPath with position (fragile)
Page.Locator("//form/div[2]/input[1]")

3. Version Control the Registry

Commit agents/selectors.registry.json to your repository. This ensures:

  • Team members have the same selector strategies
  • CI/CD can use the registry for healing
  • Historical selector data is preserved

4. Monitor Healing Events

Track when healing occurs to identify:

  • Frequently changing UI elements
  • Selectors that need attention
  • Application stability issues

Limitations

The Healer cannot repair:

  • Logic errors – If your test logic is wrong, healing won't help
  • Missing elements – If an element is completely removed from the DOM
  • Authentication failures – Network or auth issues
  • Timing issues – Flaky tests due to race conditions

The Healer focuses specifically on selector failures where the element exists but the locator strategy has changed.

Troubleshooting

Registry Not Found

If you see Registry file not found, run the learn command first:

dotnet run --project ./Agents/Agents.csproj -- learn \ --test ./Tests.E2E/Tests.E2E.csproj \ --out ./agents/selectors.registry.json

No Working Alternatives

If the Healer cannot find a working alternative:

  1. Check that the element still exists in the DOM
  2. Update the registry by running learn again
  3. Manually update the Page Object if the element was removed

Roslyn Compilation Errors

If healing produces compilation errors:

  1. Check the modified Page Object file
  2. Verify the selector syntax is correct
  3. Rebuild manually: dotnet build ./Framework/Framework.csproj

Advanced: Custom Selector Strategies

You can extend the framework to record custom selector strategies. See the Framework/Selectors/ directory for examples of how to add new locator types to the registry.