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-testattributes- 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:
- Parses test output to identify failing scenarios
- Extracts the failing Page Object and property name
- Captures the current DOM state from test artifacts
- 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:
- Loads the selector registry for the failing element
- Tests each alternative strategy against the current DOM
- Finds the first working alternative
- Rewrites the Page Object property using Roslyn
- Rebuilds the project
- 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:
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
Simulating a Failure
To test the healing mechanism:
- 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");
- Run tests to see the failure:
You'll see test failures indicating the selector cannot be found.
Healing the Tests
Run the Healer to auto-repair:
What the Healer does:
- Analyses test output to find selector failures
- Loads
agents/selectors.registry.json - For each broken selector:
- Tests alternatives from the registry
- Finds the first working strategy
- Rewrites the Page Object property
- Rebuilds the project
- 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
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:
No Working Alternatives
If the Healer cannot find a working alternative:
- Check that the element still exists in the DOM
- Update the registry by running learn again
- Manually update the Page Object if the element was removed
Roslyn Compilation Errors
If healing produces compilation errors:
- Check the modified Page Object file
- Verify the selector syntax is correct
- 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.