Locating an element by id

alecxe picture alecxe · Dec 30, 2015 · Viewed 13.9k times · Source

What is the difference between the following location techniques?

  1. element(by.id("id"));
  2. element(by.css("#id"));
  3. element(by.xpath("//*[@id='id']"));
  4. browser.executeScript("return document.querySelector('#id');");
  5. browser.executeScript("return document.getElementById('id');");

And, from the performance perspective, which would be the fastest way to locate an element by id?

Answer

SiKing picture SiKing · Jan 7, 2016

Your question is very difficult to answer, certainly to give a single conclusive answer. In fact, I am tempted to flag this question as "too broad", which is supported by the other answers and comments.

Take, for example, just your element(by.id("id"));. Looking through the Selenium source, most drivers just take whatever id you give, and pass it off to the wire protocol:

public WebElement findElementById(String using) {
  if (getW3CStandardComplianceLevel() == 0) {
    return findElement("id", using);
  } else {
    return findElementByCssSelector("#" + cssEscape(using));
  }
}

As you know, each browser vendor implements their own wire protocol in a separate binary. Feel free to go further into the code, to dig a deeper hole for your self.

For other browsers that do not support the wire protocol, for example HtmlUnit, you just have something like:

public List<WebElement> findElementsById(String id) {
  return findElementsByXPath("//*[@id='" + id + "']");
}

and then they parse the available DOM.

As for your performance question, anything that anyone gives you will be 1) just a feeling, or 2) pure BS! Which you can already see from the other answers and comments you are getting.

To get a real answer (supported by actual data), there are just too many variables to consider:

  • Wire protocol as implemented by different browser vendors, plus various optimizations in different versions.
  • DOM engines as implemented by different browser vendors, plus various optimizations in different versions.
  • JavaScript engines as implemented by different browser vendors, plus various optimizations in different versions.

Also, whatever results you get for your web app / web page will most like not apply to a different web app / web page, due to differences in the framework used to build that site.

Bottom line is: If you are concerned about performance testing, then Selenium is the wrong answer. Selenium is a functional test library, optimized to give you the best end-user representation. Performance is a distant afterthought.

If your goal is to get your tests to run faster, your time will be better spent looking at your test structure:

  • How frequently do you open/close the browser. This is often the most time consuming activity in a test.
  • How often do you refresh your element cache, how often do you need to? Consider moving your elements to Page Factory model, which lazy-loads all elements for you.
  • And of course the biggest speedup factor: running your tests in parallel on multiple machines.

But I think this is getting off topic (some might suggest "ranty") from your initial question.