What is the difference between the following location techniques?
element(by.id("id"));
element(by.css("#id"));
element(by.xpath("//*[@id='id']"));
browser.executeScript("return document.querySelector('#id');");
browser.executeScript("return document.getElementById('id');");
And, from the performance perspective, which would be the fastest way to locate an element by id?
Identifying differences would be pretty tough. Here are few things that i found -
executeScript()
schedules a command to execute JavaScript as a string in the context of the currently selected frame or window. Though this is fast, readability of code is low.element()
function in turn resolves tofindElement()
function which schedules a command to find the element on the DOM. Improved readability.From performance perspective according to me, here are the rankings in ascending order starting with the fastest and all of them were close to each other with differences in few milliseconds -
The reason for the javascript
executeScript()
being so fast is because the command its executed on DOM directly with no conversions. This link justifies their rankings between each other.The remaining protractor specific
element()
locators are slow as protractor needs to convert the commands to get the web-elements usingfindElement()
function. Getting element byid
is faster than usingcss
andxpath
(This is also dependent on how the locators are being used and often can change based on usage).NOTE: The above performance analysis was the average of many tests that i ran locally on my machine, but it can differ based on system tasks that internally affect running the test scripts.
Hope it helps.
I just think about performance perspective and write the following script to check google logo. Although the result is confusing, we can make an estimation the result statistically.
querySelector and getElementById have always better result, unless number of trials is more than 10K. If we compare these two method: getElementById is better (29 over 21).
If we compare these there, ID, CSS and XPATH, CSS is better (29 over 18 and 4), second is ID and last one XPATH.
The result from my test: getElementById, querySelector, CSS, ID, XPATH
See the table, result and script:
Table show the result in summary for 50 tries:
Result with time diff:
Code:
It would be a broad answer if someone tries to answer it so I will try to make it as simple as I can.
These are just different ways of finding elements using selenium. The reason why we have so many alternatives to select elements is, not always we will have id or class tagged to an element. For elements which do not have id or class or name the only option left with us is XPATH.
XPATH can be used to uniquely identify any element in an XML and since HTML (HTML 5 to be precise, if written according to standards) is an instance of XML we can use XPATH to uniquely identify every element in the file.
OK so why not use XPATH all the time? Why so many alternatives? Simple, XPATH is difficult to write. For example if we need to get the XPATH of a 'td' which belongs to a table nested inside 2 other tables. XPATH will be pretty long and most of the time we tend to make a mistake.
Finding XPATH in firefox is pretty straight forward, simply install firepath or firebug and right click on the element and select COPY XPATH.
Detailed instructions on indicators in selenium: here (presented in java but will help in general)
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: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:
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:
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:
But I think this is getting off topic (some might suggest "ranty") from your initial question.
TL;DR; performance in order from fast to slow.
element(by.id("id"));
element(by.css("#id"));
element(by.xpath("//*[@id='id']"));
browser.executeScript("return document.getElementById('id');");
browser.executeScript("return document.querySelector('#id');");
I will give this a try. I will try to explain it until the point of
Protractor
andWebdriverJS
. As I am not writingSelenium
or browser's drivers (E.g.Chromedriver
,Firefoxdriver
... etc...) which is the communication between browsers andSelenium
. For this I will use standard knowledge of browser's engine for this point. Therefore the answer, it will not 100% accurate but mostly.I will separate 5 methods in 2 groups:
1. Common communications
For the first 3 methods:
These are all result with a single HTTP request to Selenium server. Which is:
'/session/:sessionId/element/:id/element'
With 2 parameters:
using
: type of:id
. Example:'css select'
,'id'
, 'xpath'
,'link text'
... etc..value
: value of:id
. Example'element-id'
,'.element-css > .child'
,//*[@id='id']
At this point
Selenium
will answer the request accordingly to what is being requested through either ofChromedriver
,Firefoxdriver
... etc...Under Webdriver find-element-strategy.js . As it is seem like methods are mapped with what browser providing by javascript
document
properties. We gottag
,id
,css selector
,xpath
... etc.. which are matched withdocument.elementByTagName
,document.elementByID
,document.querySelecotr
,document.evaluate
...Logically in the point of view of a coder I will say the resource should be reuse regardless how these drivers got written. For example quest request for
id
it will most likely something likegetElementById
got to be trigger at browser side through the communication driver.=> SUMMARY So in the end we have:
css selector
equivalent ofquerySelector
id
equivalent ofgetElementById
xpath
equivalent ofevaluate
2. Injecting communications
For 2 last methods:
These are all result with a single HTTP request to Selenium server. Which is:
'/session/:sessionId/execute'
With 2 parameters:
script
: javascript text ('string'
) or afunction
args
: arguments is anarray
Until this point it with be about how JS got injected into browser, as none of us can be sure the behavior (either using
devtools
or inject<script>
into HTML). Let's just assume that it will be the same for all browser.=> SUMMARY So in the end we will analyze :
querySelector
getElementById
Main comparison
1.
element()
vsbrowser.executeScript()
:=> SUMMARY fast to slow
element()
browser.executeScript()
2.
document.querySelector()
vsdocument.getElementById()
vsdocument.querySelector()
:Again each browser will result a slightly difference. But there are already some research about this. I will just use what community has been found.
CSS selector
being know that faster thanxpath
(source)document.querySelector()
> FASTER >document.evaluate()
(NOTE: xpath is not supported by IE, so selenium using its own xpath engine whenever you are using xpath on IE with protractor)
On
jsperf.com
we got this test that sayingdocument.getElementById()
> FASTER >document.querySelector()
=> SUMARY fast to slow
document.getElementById()
document.querySelector()
document.evaluate()
3. Sum up performance of method from fast to slow
element(by.id("id"));
element(by.css("#id"));
element(by.xpath("//*[@id='id']"));
browser.executeScript("return document.getElementById('id');");
browser.executeScript("return document.querySelector('#id');");