Skip to main content
blog title image

3 minute read - Selenium WebDriver FAQs Test Automation

How to highlight elements in use with Selenium WebDriver?

Jun 29, 2020

How can we highlight the elements in use with Selenium WebDriver?

A reader asked for recommendations on how to use Selenium to make the elements in use visible.

Note: The earlier version of Selenium had a “Highlight” command. This blog post was originally written on 20100630 describing how to use that. The post has been updated in 2020 for Selenium WebDriver.

The Question

Selenium-RC had highlight which flashed the control yellow. A small helper function help debugging so people could see some indication of what elements your script touches.

I can see why you might want to to highlight the locator elements in use at the time and error happens, if you take screenshots automatically when a test fails.

And now, with the notion of “Observability”, we might consider, how can I make my automated execution visible to an external observer.

An Approach

I would start by first creating a simple class which can highlight elements.

  • Given a driver and a desired background colour
public class HighlightElement {
    private final WebDriver driver;
    private final String backgroundColour;
    WebElement lastElement;
    String lastElementOrigColour;


    public HighlightElement(final WebDriver driver, 
                            final String backgroundColour) {
        this.driver = driver;
        this.backgroundColour = backgroundColour;
    }
  • have a method which can highlight a given element
  • it also remembers which element we last added a highlight to, so that we don’t litter the page with highlighted elements
  • I’m using a very simple approach of changing the background colour of the elements.
    public WebElement highlight(WebElement newElement){

        // turn off last element
        if(lastElement!=null){
            setBackgroundColourOfElement(lastElement, 
                    driver, this.lastElementOrigColour);
        }

        lastElement = newElement;

        if(newElement!=null){

            this.lastElementOrigColour = 
                        newElement.getCssValue("backgroundColor");

            setBackgroundColourOfElement(newElement, driver,
                                         backgroundColour);
        }

        return newElement;
    }
  • the actual work of setting the background colour is done by a simple JavaScript script
  • Casting the driver to JavascriptExecutor allows running the script to change the background colour of the element
  • catch any errors just in case something goes wrong
    private void setBackgroundColourOfElement(final WebElement element, 
                                              WebDriver driver, 
                                              final String desiredColour) {

        try {
            
            ((JavascriptExecutor) driver).executeScript(
                    "arguments[0].style.backgroundColor=arguments[1]",
                            element, desiredColour);
            
        }catch(Exception e){
            if(e instanceof StaleElementReferenceException){
                // ignore
            }else {
                System.out.println("Error setting background colour of element");
                e.printStackTrace();
            }
        }
    }
}

And this could then be used in a test:

driver.get("https://testpages.herokuapp.com/styled/index.html");

highlighter.highlight(
        driver.findElement(By.id("htmlformtest"))
    ).click();

highlighter.highlight(
        driver.findElement(By.name("username"))
    ).sendKeys("Bob");

This would allow adhoc highlighting if needed.

What if highlighting was always on?

To make highlighting always on, I would want to do that at a driver level and could use an EventFiringWebDriver with a listener which trapped:

Some interaction events:

  • beforeClickOn
  • beforeChangeValueOf

And the ‘find’ event:

  • afterFindBy

And this would basically delgate off to the HighlightElement class we created earlier.

public class ElementHighlighter implements WrapsDriver {
    EventFiringWebDriver driver;

    public ElementHighlighter(final WebDriver aDriver, 
                              final String desiredBackgroundColour) {
        
        driver = new EventFiringWebDriver(aDriver);
        driver.register(new ElementHighlighterListener(
                                    driver, desiredBackgroundColour));
    }

    @Override
    public WebDriver getWrappedDriver() {
        return driver;
    }

    private class ElementHighlighterListener extends
                             AbstractWebDriverEventListener {

        HighlightElement highlighter;

        public ElementHighlighterListener(WebDriver driver, 
                                          final String highlightColour) {
            
            highlighter = new HighlightElement(driver, highlightColour);
        }

        @Override
        public void beforeClickOn(final WebElement element,
                                final WebDriver driver) {
            
            highlighter.highlight(element);
            super.beforeClickOn(element, driver);
        }

        @Override
        public void beforeChangeValueOf(final WebElement element, 
                                        final WebDriver driver, 
                                        final CharSequence[] keysToSend) {
            
            highlighter.highlight(element);
            super.beforeChangeValueOf(element, driver, keysToSend);
        }

        @Override
        public void afterFindBy(final By by, final WebElement element, 
                                final WebDriver driver) {
            
            highlighter.highlight(element);
            super.afterFindBy(by, element, driver);
        }
    }
}

Full Source

The full source for this is in my Webdriver Java FAQs project:

Specifically:

If you want to learn how to use Selenium WebDriver with Java then check out our online courses.