I have tested the Gmail login page and was trying to verify the Sign in label in the Gmail login page above the user name field. I am using FirePath to generate the Xpath. When I inspect the element Sign in using Firebug, FirePath generated the absolute Xpath html/body/div[1]/div[2]/div[1]/div/h2
. When I copy this Xpath and execute it, the testcase fails. Adding //
to the absolute Xpath works, i.e. //html/body/div[1]/div[2]/div[1]/div/h2
. To summarize, the absolute Xpath works with /
(single slash) whereas relative Xpath works with //
. Can anyone correct my mistakes or explain this?
-
A more general question comes to my mind: Why don't you use Ids instead of XPaths to locate elements? Ids seems easier to read for a human, more stable and reliable in this particular context. And Gmail Web page provides them :-)– dzieciouAug 31, 2013 at 15:10
-
You can use this //h2[contains(text(),'Sign in ')] for label– Abhishek SInghFeb 22, 2017 at 6:16
4 Answers
As much as possible, please avoid using absolute xpaths, any small change in the page layouts and your xpaths may become completely useless, as much as possible, use the class names, ids etc... For the gmail sign-in,
//div[@class='signin-box']//div[@class='email-div']//input[@id='Email']
is the xpath for the UserName Text field, likewise for the password field, it'd be
//div[@class='signin-box']//div[@class='passwd-div']//input[@id='Passwd']
-
1Excellent suggestion - it makes a lot of sense to work with relative paths. Using class and ID identifiers - which change a lot less often than page layouts - is a good way of saving yourself heartache later.– Kate Paulk ♦Aug 30, 2013 at 11:30
-
Might be a bit off-topic comment, but... why work with XPath at all, if you refer to elements' ids in them? Why don't you simply locate elements
By.id()
?– dzieciouAug 31, 2013 at 15:09
From my experience, sometimes the way XPaths are read by Selenium are different from what you expect, especially if you've verified the XPaths are correct in Firepath.
Yes, both of the XPaths you've posted point to the same element and should work identically, but for some reason, only the relative one is working correctly in the IDE.
The main takeaway from this is to avoid absolute XPaths like the plague! Always use relative ones, but make them more specific, so other elements aren't found instead (since Selenium picks the first out of all the matches).
This is nice and short://div/h2
. But if there are any other h2 elements on the page before this one, they will be found as well.
If you want to be more precise, try: //div/h2[contains(text(),"Sign in")]
.
I tested each of the above with Firepath and Selenium IDE and they work.
You mentioned three ways to start an Xpath. /html
matches a html tag at the top of the document. //html
matches any html tag anywhere in the document. html
matches any html tag that is a child of the context element. I do not know how Selenium 2 defines the context element. If the context element is not the top of the document, you will get the behavior you observed.
If you have not read the sections of the W3C Xpath specification on locations and abbreviations, you may benefit from doing so. It is not very long.
-
You're correct about /html and //html, but the Selenium IDE isn't recognizing /html and any element that follows it (at least on that Gmail login page). I think that's what the OP was confused about. May 8, 2012 at 20:26
I would suggest never use complete xpath in any UI test. And the reason is if anything gets change in the UI structure then your test will fail. And there will be huge cost towards maintaining your test cases. So for any UI test we should try to identify elements based on their unique id/class/div name etc.
For your case to find out sign in link you can use the following command:
selenium.GetText("//div[@class='signin-box']/h2");
Hope this will help you.
-
If you use PageObject design pattern, the cost of maintenance can be much lower. If page structure changes, you will need to update only one class.– dzieciouAug 31, 2013 at 14:58