Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the most efficient selector to use with findElement()?

When working with Selenium web testing, there are a few ways to identify WebElements.

In my experience, I have used the following selectors:

  • Class Name - By.className()
  • CSS Selector - By.cssSelector()
  • ID - By.id()
  • Link Text - By.linkText()
  • Name - By.name()
  • Tag Name - By.tagName()
  • XPath - By.xpath()

Obviously, when only one option is usable to locate an element, we must use that one, but when multiple methods may be used (ex: the div below), how should it be determined which method to use? Are there selectors that are more efficient than others? Are there some that are more durable?

<div class="class" id="id" name="name">Here's a div</div>
like image 881
Pseudo Sudo Avatar asked Dec 06 '16 17:12

Pseudo Sudo


2 Answers

Just for s&gs...

I timed each of the identifier methods finding the div above five separate times and averaged the time taken to find the element.

WebDriver driver = new FirefoxDriver();
driver.get("file://<Path>/div.html");
long starttime = System.currentTimeMillis();
//driver.findElement(By.className("class"));
//driver.findElement(By.cssSelector("html body div"));
//driver.findElement(By.id("id"));
//driver.findElement(By.name("name"));
//driver.findElement(By.tagName("div"));
//driver.findElement(By.xpath("/html/body/div"));
long stoptime = System.currentTimeMillis();
System.out.println(stoptime-starttime + " milliseconds");
driver.quit();

They are sorted below by average run time..

  • CssSelector: (796ms + 430ms + 258ms + 408ms + 694ms) / 5 = ~517.2ms
  • ClassName: (670ms + 453ms + 812ms + 415ms + 474ms) / 5 = ~564.8ms
  • Name: (342ms + 901ms + 542ms + 847ms + 393ms) / 5 = ~605ms
  • ID: (888ms + 700ms + 431ms + 550ms + 501ms) / 5 = ~614ms
  • Xpath: (835ms + 770ms + 415ms + 491ms + 852ms) / 5 = ~672.6ms
  • TagName: (998ms + 832ms + 1278ms + 227ms + 648ms) / 5 = ~796.6ms

After reading @JeffC 's answer I decided to compare By.cssSelector() with classname, tagname, and id as the search terms. Again, results are below..

WebDriver driver = new FirefoxDriver();
driver.get("file://<Path>/div.html");
long starttime = System.currentTimeMillis();
//driver.findElement(By.cssSelector(".class"));
//driver.findElement(By.className("class"));
//driver.findElement(By.cssSelector("#id"));
//driver.findElement(By.id("id"));
//driver.findElement(By.cssSelector("div"));
//driver.findElement(By.tagName("div"));
long stoptime = System.currentTimeMillis();
System.out.println(stoptime-starttime + " milliseconds");
driver.quit();
  • By.cssSelector(".class"): (327ms + 165ms + 166ms + 282ms + 55ms) / 5 = ~199ms
  • By.className("class"): (338ms + 801ms + 529ms + 804ms + 281ms) / 5 = ~550ms
  • By.cssSelector("#id"): (58ms + 818ms + 261ms + 51ms + 72ms) / 5 = ~252ms
  • By.id("id") - (820ms + 543ms + 112ms + 434ms + 738ms) / 5 = ~529ms
  • By.cssSelector("div"): (594ms + 845ms + 455ms + 369ms + 173ms) / 5 = ~487ms
  • By.tagName("div"): (825ms + 843ms + 715ms + 629ms + 1008ms) / 5 = ~804ms

From this, it seems like you should use css selectors for just about everything you can!

like image 142
Pseudo Sudo Avatar answered Sep 18 '22 12:09

Pseudo Sudo


In my experience, I use these locators in this order:

  1. id
  2. linkText/partialLinkText
  3. CSS Selector
  4. XPath

The others: class name, tag name, name, etc. can all be found using CSS selectors. I rarely need a single class name so I prefer CSS selector so that I can use more than one class but also specify a tag name to make it more specific and less likely to break. Tag name is rarely used... unless we are talking about a TABLE or TR or TD tags and those can all be done with CSS Selectors. I generally find that tags with a name also have an id so I prefer id.

I recently found, as you did in your answer, that CSS selector is the fastest. This makes sense because Selenium is using the browser to do the searches and CSS selectors are so common that the different browsers have optimized performance for their use.

linkText/partialLinkText are very specialized so I don't really count them. I use them when I can and it makes sense. I have thought about just using By.cssSelector("#someId") but I don't think it really makes that much of a difference and By.id() is just a little more obvious when using an Id.

I rarely use XPath and only when I can't accomplish it with other locators, e.g. in the case of text from a tag or some weird child/descendant thing that I can't do with CSS selectors. I found (and read) that XPath support is varied by browser and it's slower so I avoid it unless absolutely necessary... and I have found you can locate 99% of elements with #1-3.

ids should be the most durable. LinkText and partialLinkText are probably fairly durable, depending on the page. Classes applied and the structure of the HTML that you would use with CSS selectors are probably the most likely to change with a page update. It really depends on the size of the update as to whether a partial portion of a page is changed. CSS Selectors and XPath would both (generally) be affected by these sorts of changes.

In the end... as long as you aren't scraping the page for hundreds of elements, one page transition is likely to be WAY more significant than a few hundred ms of difference between locator methods.

like image 44
JeffC Avatar answered Sep 18 '22 12:09

JeffC