Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Quickly get class attribute of every WebElement with Selenium in Java

I'm looking to get the class attribute of every WebElement on the page quickly with selenium. Currently, I'm doing the following:

allElements = new ArrayList<WebElement>(m_webDriver.findElements(By.cssSelector("*")));

for (WebElement element : allElements) {
    String className = element.getAttribute("class");
}

This process is incredibly slow, taking upwards of thirty seconds on a page with 500 elements. I've tried parallelizing the getAttribute call, which is the slowest part of the method, but there was no speed increase. This leads me to believe that every call to getAttribute is fetching information instead of storing it locally.

Is there a faster or parallelizable way to do this?

like image 469
JordanKrissi Avatar asked Jun 08 '15 18:06

JordanKrissi


People also ask

How do you fetch an attribute value of an element in Selenium?

The getAttribute() method fetches the text contained by an attribute in an HTML document. It returns the value of the HTML element's attribute as a string. If a value is not set for an attribute, it will return a NULL value. For attributes with Boolean values, getAttribute() will return either "True" or NULL.

How do I find the class of an element in Selenium?

We can find an element using the attribute class name with Selenium webdriver using the locators - class name, css, or xpath. To identify the element with css, the expression should be tagname[class='value'] and the method to be used is By. cssSelector.

How do I get CSS properties of a WebElement?

We can get the css class name of an element with Selenium webdriver. To obtain the class name attribute of an element in the html document, we have to use the getAttribute() method. Then the class value is passed as a parameter to the method.

How do I retrieve CSS properties in Selenium?

Type “css=input[type='submit']” (locator value) in Selenium IDE. Click on the Find Button. The “Sign in” button will be highlighted, verifying the locator value. Attribute: Used to create the CSS Selector.


2 Answers

The problem is, you cannot make selenium send batch getAttribute() calls for multiple elements. Here is a similar problem I've looked into - it is about making isDisplayed() work for multiple elements without making JSON Wire protocol requests for every element in a list:

  • How can Selenium batch many isElementDisplayed calls?

But, as opposed to this isDisplayed() problem, here we can execute javascript and reliably get the class attribute values for every element on a page, something like this to get you started:

JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("var result = []; " +
"var all = document.getElementsByTagName('*'); " +
"for (var i=0, max=all.length; i < max; i++) { " +
"    result.push({'tag': all[i].tagName, 'class': all[i].getAttribute('class')}); " +
"} " +
" return result; ");
like image 131
alecxe Avatar answered Oct 23 '22 05:10

alecxe


I would keep it simple and use an XPath instead of a complex snip of Javascript:

// get all elements where class attribute is not null
List<WebElement> allElements = m_webDriver.findElements(
  By.xpath(".//*[@class and not(ancestor::div[contains(@style,'display:none')])]")
);

for (WebElement element : allElements) {
    String className = element.getAttribute("class");
}
like image 28
djangofan Avatar answered Oct 23 '22 06:10

djangofan