Overview of Self-Healing Automation

Self-healing test automation identifies changes in an application’s UI and automatically updates test scripts to adapt to these changes. By handling locator failures, self-healing can minimize test disruptions due to minor application updates, reducing the need for manual maintenance (testRigor, Ministry of Testing).

Setting Up in vscode

Install Selenium and Setup Web Driver:

Google Colab cannot handle browser automation well, so we’ll install Selenium and a Chrome driver in python (I will refer you to my course about python testautomation how to do this)

Example Self-Healing Script:

The script will include a self-healing function to locate elements dynamically. We will use a primary locator and a backup locator to simulate a self-healing mechanism.

Explanation of the Script:

The script opens a web page, tries to interact with an element, and automatically switches to a secondary locator if the primary one fails.

Code Walkthrough

Below is a practical example you can run in Google Colab.

# Step 1: Install Selenium and download Chrome driver
!pip install selenium
!apt-get update
!apt install -y chromium-chromedriver
!cp /usr/lib/chromium-browser/chromedriver /usr/bin

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options

# Step 2: Set up Chrome options for Google Colab
chrome_options = Options()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--disable-dev-shm-usage')

# Initialize the Chrome driver
service = Service('/usr/bin/chromedriver')
driver = webdriver.Chrome(service=service, options=chrome_options)

# Step 3: Define the self-healing function
def find_element_with_self_healing(driver, primary_locator, secondary_locator):
    try:
        # Try the primary locator
        print("Trying primary locator...")
        return driver.find_element(*primary_locator)
    except NoSuchElementException:
        print("Primary locator failed. Trying secondary locator...")
        # Fall back to secondary locator
        return driver.find_element(*secondary_locator)

# Step 4: Visit a website for demonstration
driver.get("https://example.com")

# Define locators
primary_locator = (By.ID, "non_existent_id")  # A locator that we expect to fail
secondary_locator = (By.XPATH, "//h1")  # A backup locator

# Step 5: Find element using the self-healing function
element = find_element_with_self_healing(driver, primary_locator, secondary_locator)

# Interact with the element if found
if element:
    print("Element found! Text:", element.text)
else:
    print("Element not found!")

# Close the driver
driver.quit()

Explanation of Code

Self-Healing Function:

The find_element_with_self_healing function first attempts to locate the element with a primary locator. If it fails, it catches the NoSuchElementException and tries again using a secondary locator.

Running the Script:

When you run the script, it attempts to locate an element by ID (which is intentionally set to fail). It then falls back on an XPath locator to find the element.

Benefits:

This simple example shows how self-healing can make tests more resilient to minor changes in the UI, as it adapts to locator failures.

But how do we impelement AI and Machine learning into the mix:

How Generative AI (LLM) Can Enhance Self-Healing Automation

Generative AI, like large language models (e.g., GPT-4), can significantly improve self-healing test automation through its ability to process and understand complex data patterns and generate new code or logic in real time. Here’s how an LLM can complement or enhance the self-healing mechanisms:


1. Dynamic Locator Generation

LLMs can analyze the webpage structure and generate more robust locators on the fly if traditional locators (ID, XPath) fail. This goes beyond simple fallback strategies by allowing the model to generate customized locators based on context, element hierarchy, or even visible text.

For example, if a button label changes, the LLM can be prompted to generate a new locator based on text recognition and the general layout of the UI. This approach could be more adaptable than a fixed machine learning model, as it uses natural language processing to interpret the layout more like a human would.


2. Locator Healing Suggestions Based on Context

LLMs can interpret changes in the UI by recognizing the intent of the test step based on previous actions and page content. For instance, if a button’s ID changes but the action is still “click the submit button,” the LLM can identify similar elements or nearby components that align with the intended action.

This helps in cases where traditional locators are not enough, such as testing applications with dynamically generated elements or frequent layout changes.


3. Natural Language-Based Test Generation and Repair

With natural language capabilities, LLMs can take test cases written in plain English and convert them into executable Selenium scripts. This allows testers to write self-healing tests using natural language, simplifying test creation.

When a test fails, an LLM can analyze the error message, infer the cause, and propose a fix. For example, if an element is no longer visible, the LLM could suggest an alternative action, such as scrolling to the element or waiting for it to appear.


4. Learning and Adapting from Test History

Unlike traditional ML models that require retraining, LLMs can dynamically analyze test execution history and adapt to new patterns. This is beneficial in environments with continuous delivery where application changes are frequent.

The LLM can analyze past test results, identify recurring failure patterns, and adjust locators or recommend updates to the test suite in real-time without manual intervention.


5. Enhanced Error Analysis and Reporting

LLMs can provide detailed explanations of why a test failed, describing potential reasons in natural language. For instance, if an element is not found, the LLM can suggest that the element might have been removed, renamed, or hidden by recent code changes.

Practical this means extending selfhealing with AI:

Enhancing LLM-Based Self-Healing with DOM Context and Attributes

1. DOM Context in the Prompt

You can extract relevant portions of the DOM and include them in the prompt. For example, if you’re working with a specific section of the webpage, you could pass the LLM a snippet of the HTML code around that section. This provides context for the LLM to understand the layout and make more accurate suggestions.

In practice, this means:

# Example: Get HTML for a specific section and include it in the LLM prompt
section_html = driver.page_source  # Or a more targeted HTML extraction
prompt = f"Here is a part of the HTML: {section_html}. I couldn't locate an element with ID 'checkbox'. Suggest an alternative locator for an element that matches this section."

2. Element Attributes

If you know specific attributes that describe the element, you can include them in the prompt. For example, you might include attributes like class, name, placeholder, or even nearby text. This can help the LLM infer the purpose and position of the element within the page.

Example:

element_attributes = {"class": "main-header", "tag": "h1"}
prompt = f"An element with these attributes: {element_attributes} could not be found. Please suggest a new XPath or CSS selector to locate it."

3. Page Structure and Element Descriptions

Providing the LLM with a description of the webpage’s structure or the element’s function can help it make educated guesses about the element’s position. For example, you could describe that an element is usually “the first button in the navigation bar” or “an input field following a label with specific text.”

Including this information in the prompt:

prompt = "The element is a submit button following a label with text 'Email'. The button has no unique ID but is often located at the bottom of the form. Suggest a locator for it."

4. Automating DOM Extraction

You can write a script to extract elements dynamically (like tag names, classes, and IDs of nearby elements) to provide as context to the LLM. By analyzing the DOM structure surrounding the failed element, you can give the LLM a snapshot of the layout in which it needs to locate the element.

Including this information in the prompt:

# Example code snippet to extract neighboring element attributes
target_element = driver.find_element(By.ID, "target_id")
neighboring_elements = target_element.find_elements(By.XPATH, "./preceding-sibling::*")
neighboring_info = [(elem.tag_name, elem.get_attribute("class")) for elem in neighboring_elements]

prompt = f"The target element is missing. Nearby elements are: {neighboring_info}. Please suggest an alternative locator for an element similar to this structure."