Identify objects in selenium - selenium

In my application, it has several tabs, say 'AAA','ABC','ADF'; I need to automate the click on tab 'ABC'.
Those tabs have ids and they are 'tab1','tab2','tab3'. I can done this easily by using ids. but i don't want to use this because those tabs will change time to time. so I need to use the name in the tab, because it is unique.
Below is my tag:
<a id="tab2" class="current" onclick="expandcontent('sc2', this);" href="#"> ABC </a>

If this is the case, you will probably need to fall back to XPath and perform text-based searches, for instance:
//a[text()='ABC']
Though, I'd advise you work with your development team to have consistent ID's. Text based matching is fine, but when you start to use older browsers you'll notice it really really slows down the tests.
However, you can also use the .LinkText and .PartialLinkText selectors in your language API's - there should be an implementation of those selectors in each API (C#, Ruby, Python etc). The catch here is this will be for a (anchor) elements only. However, providing that is the only type of elements this needs to be done by, you can get away with using this instead of XPath.

As Arran mentioned, you are likely best off searching for the tab names using XPath but, you can also use FindBy as well. An example of this would be:
#FindBy(css=<the CSS value for the tab>) private WebElement pageTab2;
#FindBy(id="tab2") private WebElement pageTab2;
I can only agree with what Arran also mentioned about your developers using more relevant naming conventions as well. The easier they make your job, the more you can do to make their lives easier too.

Simplest answer will be Use..."link=ABC" or link=" ABC " (it there are leading and trailing spaces).

The simplest approach would be to use X paths to find your tabs.
When you are starting out there are two helpful tools to help you find X paths. Download Mozilla Firefox and get these two add-ons:
Web Driver Element Locator-After downloading you can right click a web element and select X path.
Selenium IDE-This is a recorder and will give you the X paths or CSS of each web element you interact with.
I would recommend starting with these tools to help you out since you are just starting out.
As for your question:
I would recommend using what #Arran said...
//a[text()='ABC']
'a'-will search the entire page for whatever text you have in single quotes ''
If you Right Click the element or Tab and select Inspect. You will then be looking through the back-end of the page for classes or div that help you identify each different element.

xpath=//a[contains(#class,"current") and contains(#text,"ABC")]

Related

How to identify an element without using xpath when id name is not available in selenium

There are few elements in an UI page without ID. I will download a particular version and then save all the current element tags and give to script as input, since few elements are not having id, this is causing script failures.
How can I locate the element without using Xpath.
Is there any simple way when there is no fixed id.
The short answer is "no." Sorry. All of the usual ways (by id, class, etc.) are relying on the same css information to locate elements. Xpath just shows all the ugly plumbing out in public. I don't think xpath has ever been described as "simple" but there is usually a way, using xpath, to find any element.
Xpath can be intimidating. Start with a plugin that will generate the xpath for you, once you click on an element. Usually the xpath generated will be extremely long and inefficient, but with practice you can see what can be trimmed and what is crucial. And to do that, also use a plugin that will "check" your xpath to see if it can find the element. Once you can find it (and ONLY the element you want) try trimming it to see if you can still find it with the abbreviated xpath locator.
reference ImageDon't be afraid of Xpaths. It's relatively easy to grab an Xpath using the Google Chrome browser. Navigate to your page and open Developer tools. Right-click on the particular tag for which you need an Xpath. Copy -> Xpath

Identifying the same Web Elements with Selenium

I am an Automation Engineer, I am currently trying to create test cases for a webpage that are sustainable ( that I can run at a later time and have still pass)
Here is my problem:
I am trying to select multiple web buttons that have the same exact class name. Now I can 'select' these buttons but these are only temporary x paths that are subject to change.
I need UNIQUE ID's (or some way of distinguishing them) for the same web elements. The only difference in the x paths are:
HTML format code that I can find each button, however if one button is moved my tests will fail.
HTML code that is the class name + nth of the button. But again my tests will fail if a button is taken out of the webpage.
//*[#id="tenant-details-accordion"]/div[1]/div[2]/div/div[2]/div[1]/div/a/div
//*[#id="tenant-details-accordion"]/div[1]/div[2]/div/div[2]/div[2]/div/a/div
//*[#id="tenant-details-accordion"]/div[1]/div[2]/div/div[2]/div[3]/div/a/div
^^The above code is how I currently find each button with Selenium
If I copy each classes x path this is what I get
<div class="src-js-components-DateControl-___DateControl__dateControl___2nYAL"><a tabindex="0"><div class="src-js-components-DateControl-___DateControl__icon___2z6Ak null"></div><!-- react-text: 392 -->Set +<!-- /react-text --></a></div>
<div class="src-js-components-DateControl-___DateControl__dateControl___2nYAL"><a tabindex="0"><div class="src-js-components-DateControl-___DateControl__icon___2z6Ak null"></div><!-- react-text: 386 -->Set +<!-- /react-text --></a></div>
<div class="src-js-components-DateControl-___DateControl__dateControl___2nYAL"><a tabindex="0"><div class="src-js-components-DateControl-___DateControl__icon___2z6Ak null"></div><!-- react-text: 398 -->Set +<!-- /react-text --></a></div>
I have talked to the Development team about this issue however they tell me that assigning Unique ID's to these web elements is a big no-no. (something to do with globalization of the project when we go to production) Even if they did assign Unique Id's they tell me that they would have to strip them before the project can be sent to production. Which ultimately would render my tests useless in the end...
I now come to Stack Overflow for help, everything I look up online cannot give me an answer, however this does seem to be a valid question between QA and Development departments.
Is there a way to assign Id's to a web element so that a tester using selenium can identify them and yet it will not affect a Developers ability to use that element through an entire project?
Edit:
With the framework that my company uses, I am not actually writing any code in selenium. I save the Xpath to an object and then later in a manual test call that object with a pre-existing method. I can ONLY select Xpaths to be saved in an object.
I'll talk to Dev later to have them explain the big 'no-no' so that I may be able to communicate that with all of you..Thank you for your time and input
For example:
BirthDateSet= someXpath
Click() using {BirthDateSet}
Here are some pictures to help give you a visual
You can simplify your XPathto make it less sensitive to possible changes in DOM:
//div[#class="src-js-components-DateControl-___DateControl__icon___2z6Ak null"][N] # Where N is button index
If this part 2z6Ak of class name is dinamically generated, try:
//div[starts-with(#class, "src-js-components-DateControl-___DateControl__icon___")][N] # Where N is button index
Another way of reaching to the required button using xpath is following:
//*[#id='tenant-details-accordion']/descendant::div[contains(#class, 'DateControl__icon')][1]
Above xpath should be able to select the first occurring button. Similarly, for the second occurring button, the xpath will become:
//*[#id='tenant-details-accordion']/descendant::div[contains(#class, 'DateControl__icon')][2]
Hence, you can continue to replace the predicate([2]) based on occurrence level of the required button on page.
you can ask devs to add attribute to those buttons
so instead of:
<button class="common_class_name">
<button class="common_class_name">
<button class="common_class_name">
for each button you will see
<button class="common_class_name" test-id="uniqueAttributeForButton1">
<button class="common_class_name" test-id="uniqueAttributeForButton2">
<button class="common_class_name" test-id="uniqueAttributeForButton3">
etc
And in your tests you can find those buttons using css selector
e.g. C# code:
var buttonLocator = "[test-id=\"uniqueAttributeForButton1\"]";
WebElement button = driver.FindElement(By.CssSelector(buttonLocator));
if devs doesnt want to add unique IDs or attributes (it's weird why they don't want to do that) you could try something like this:
//return div class 'col-sm-4' which contain text 'Activation Date'
var parentDiv = driver.FindElement(By.XPath("//div[contains(#class, 'col-sm-4') and contains(., 'Activation Date')]"));
//should return div with icon you want e.g. Click
var childElement = parentDiv.FindElement(By.CssSelector(".DateControl__icon"));
childElement.Click();
You can go with the nth approach to find your unique element or with another, that won't solve your real problem which is that your colleague developers aren't cooperating with you. The automated tests are supposed to be (among other things) a service for the developers to know they haven't broken anything as fast as possible, but if they aren't giving any effort, then WHY should you invest in it at all..?
They probably won't even look at the results. Especially when your locators are in the form of div[2]/div[3]... which would break very often and you'll lose their trust in the automation.
I'm no front-end expert but I've seen enterprise products in production with G10N and L10N and other long words, that have id's in their HTML, so if I were you I'd dig deeper to understand why? that big no-no, which sounds very odd to me...
So you asked the wrong question, it should be something like ~ How to add unique id's to the HTML using React in a global web application? and the ones who should be asking it are the developers.
As a side note, as many people tend to think, automation is not mainly about moving manual tests to automated it also finds "bugs" in the communication inside the company. To quote a great blog post on this subject:
Counter-intuitively, the bigger obstacles when developing automation
are either low priority bugs or even things that are not bugs
whatsoever. These obstacles can be symptoms of a bad design, bad
development practices and even symptoms of inefficient communication
patterns in the organization (that are usually caused by the
organizational structure! Conway’s law is a classic example for this).
Good luck!
EDIT:
Thanks for the code.. So if you look at your code, you can see that although what you're after have similar attributes, there are elements in the page that would allow you to identify what you're after. So let's say you want the SET link after Birth Date, then use:
//div[contains(text(),'Birth Date')]/div/a/div
So to reuse this xpath, just replace the text String.format("//div[contains(text(),'%s')]/div/a/div", labelName);
OLD: if you want to temporarily assign the elements an attribute, I believe you can do that through javascript element.setAttribute() which you can run through the executeScript() function.
Don't the buttons have text? Are you saying that the buttons swap places with one another? or don't you want to use the index of the buttons?
I understand you want to select the "Set +" buttons, correct?
If so you can try to find all buttons under the #id="tenant-details-accordion" element with a specific text like that:
//*[#id="tenant-details-accordion"]//*[text()='Set +']

Finding clickon Element using Selenium. (JAVA)

I spend hours already trying to find the way to find the Element using Selenium WebDriver. I assume I need to use driver.findElement(By.xpath("")), but I am not quite sure how.
I somehow need to find and click on "clickon" element. The problem is that part of that element is changing (see screenshot) I need to pick up from the file and putted into the xpath.
I would appreciate any help.
We have been rigorously searching for automated functional testing solutions recently, and we began with Selenium. The entire reason we decided to search for other solutions was that our application also has dynamic IDs with no other obvious XPath mechanism to identify them. Selenium is unable to identify these elements on the page without some additional knowledge, just as you would be unable to identify these elements on the page if you didn't already know what they are.
If you are controlling the DOM creation, consider adding a unique ID or class to this element.
We recently came across eggPlant from testPlant, and it is an interesting approach to functional testing. It's essentially image based. Other viable solutions are Ranorex or HP's QTP or SmartBear's TestComplete.
You can use xpath. If the div class is constant, you can use something like:
driver.findElement(By.xpath("list-row field-item")).click();
To view the xpath, you can install firefox plugin called 'xpath checker' found here and right click on the dom element and click 'View Xpath' option to get the xpath of the element and then you can use that xpath in your code.
Or you can even use regex in the xpath which is suitable for the similar problems. Xpath with regex is really powerful.
It seems that you want to click the div that has the on click attribute that contains certain text that doesn't change, ignoring the part that does. In that case, use an xpath like this:
//div[contains(#onclick, '/challenge/index/rfp_id/')]
This will select the first div with an onclick attribute with a value containing /challenge/index/rfp_id.

How to handle dynamic id from xpath

I am trying to explore IDE with this site http://www.barnesandnoble.com/, by just recording and play back.
1.In the search box just enter any text to search,
2.Ten click on All Products, select Books.
When i record its xpath is as below
/html/body[#id='CDS']/div[#id='navContainer']/div[#id='bnnav2011']/div[#id='yui_3_3_0_1_1355746621091_93']/div[#id='bn-global-header']/div[#id='yui_3_3_0_1_1355746621091_92']/div[#id='yui_3_3_0_1_1355746621091_91']/form[#id='qs']/div[#id='yui_3_3_0_1_1355746621091_90']/div[#id='yui_3_3_0_1_1355746621091_89']/ul[#id='yui_3_3_0_1_1355746621091_88']/li[#id='yui_3_3_0_1_1355746621091_99']
But when we play ti again it gives error,[error] locator not found:
Wehn i search for its xpath , its chnaged and is as below
/html/body[#id='CDS']/div[#id='navContainer']/div[#id='bnnav2011']/div[#id='yui_3_3_0_1_1355748592221_91']/div[#id='bn-global-header']/div[#id='yui_3_3_0_1_1355748592221_97']/div[#id='yui_3_3_0_1_1355748592221_96']/form[#id='qs']/div[#id='yui_3_3_0_1_1355748592221_95']/div[#id='yui_3_3_0_1_1355748592221_94']/ul[#id='yui_3_3_0_1_1355748592221_93']/li[#id='yui_3_3_0_1_1355748592221_98']
Observe that, its ID's are changing.
Can any one tell me how to handle this ?
The IDE is not very smart at generating XPath queries, in fact, there isn't an automated tool out there that will calculate a reliable XPath query. Why? The reason is because to generate the XPath query, it will walk down the tree from the top (at the html element), down to the element you are interacting with.
Whilst this is fine for a lot of things, if you have elements that have dynamic values (dynamic text/ID/name/classes or even if it changes position), it's never going to work.
You'll need to look at a different way to get it, so you'll have to override what the IDE is giving you.
Looking at the source, they give whatever is selected a class value of ui-selectmenu-selected. So when the page loads, the 'All Products' list item (li) will have that class, when you change the item the new item will have that class.
So you could use this XPath:
//li[#class='ui-selectmenu-selected']
Or, this CSS selector:
li.ui-selectmenu-selected
Or, use this XPath to get the 'All Products' item specifically. It will start one level up, using the actual menu, then go down and find the item:
//ul[#class='ui-selectmenu']/li[text()='All Products' and not(#class='ui-selectmenu-hidden')]
You can try using xpath: Position. It seems that the IDs are changing all the time.
As an answer to your question you should move away from id's and try using xpath or css selectors where you can select the nth child of the parent.
Since you are new to selenium I would like to point to my notes here at.-
http://selenium-testing-notes.blogspot.in/
it will help you through a lot of other pitfalls I fell in.
The best way I found to help with selectors is to work with firebug with firepath installed. This setup can help you verifying your xpath and css selectors.
I saw your question based on that answer is first you need to add on fire-path in Firefox .Using firepath you can find the xpath locator. it is very simple to you
Example:
driver.find_element_by_xpath("see![image which i have attached in this question][1] the xpath path locator details").click()
Hi Arran i am able to click the All Products button using the xpath you have given ( xpath= //ul[#class='ui-selectmenu']/li[text()='All Products' and not(#class='ui-selectmenu-hidden')]
and also get the list available. But then not able to click the Books item from the Menu.

Verifying text is present within certain element

When creating selenium tests using the #{selenium} tag, how do you use complex XPath locators? I've got some simpler examples that work but I'd really like to avoid having to give every element an id just to facilitate testing.
I've tried variations like these:
#{selenium 'Sitemap'}
...
// These work:
assertTitle('Site Map')
verifyTextPresent('Site Map')
verifyTextPresent('Login')
verifyText('id=test', 'Login')
verifyText('//ul', 'Login')
verifyText('//ul[2]', 'Login')
// this one results in "Element //ul[#class=sitemap] not found"
verifyText('Login','//ul[#class=sitemap]')
#{/selenium}
Has anyone gotten the more complex versions working? It looks like it should work according to the selenium docs. Also, is the creation of selenium tests in the context of Play documented anywhere? The only mention of it that I can find are these trivial examples.
I disagree to a degree. Badly constructed xpaths that search through the entire DOM will slow down tests but well constructed xpaths should have minimal effect on speed (unless you are using IE which has a horrific JavaScript rendering engine).
Ideally you want to key your xpath to an ID as close to the area of the DOM you want to search as possible, this will ensure you are only searching a specific area of the DOM rather than using an xpath like the one shown above that will search through the entire DOM even it it does find a matching element quickly.
I'll provide some examples of what I would call good xpaths using http://www.lazeryattack.com as an example. If you have anything specific in mind shout and I'll see what I can do to help:
The Voice Comms link: //ul[#id='leftMenu']/li/a[.='Voice Comms']
H3 element that contains a span element with the text "January VAT Increase": //div[#id='news']/h3[span[.='January VAT Increase']]
The first paragraph of text under the above element: //div[#id='news']/h3[span[.='January VAT Increase']]/following-sibling::p[1]
The second paragraph of text under the above element: //div[#id='news']/h3[span[.='January VAT Increase']]/following-sibling::p[2]
Start searching from the featuredNews div and drop down to the h2 element with the text "New Look And Feel": //div[#id='featuredNews']/descendant::h2[.='New Look And Feel']
I would suggect using FireFox with the FireBug and FirePath extensions to help you work out xpaths, this is my personal favourite combination.
Did you try
//ul[#class='sitemap']
Notice the single quote around sitemap.
XPath would make your tests slow and id, name are better option to use.