7

I have a problem with the two same XPath with dynamic ID on the same page. I have tested for selenium in java, when I need to confirm button on delete upload file. Instead of this, test first submits the first button in order on delete whole record.

Both buttons are connected with a modal window so I need to locate the second button instead of the first button on the page. XPath looks like this:

//*[@id="button-with-dialog-modal-confirm-action-button-0XP"]/span
3
  • You can simply select it by index. i.e for first button (//*[@id="button-with-dialog-modal-confirm-action-button-0XP"]/span)[1] Dec 29, 2017 at 18:24
  • I already used this but it didn´t work because id is always different (0XP-it is dynamic ID even this is not functional By.xpath("//*[starts-with(@id,'button-with-dialog-modal-confirm-action-button--')]/ span)[1]"))); :-( Jan 2, 2018 at 13:17
  • 1
    I would not spend time designing such complicated (and as you found, fragile) Xpath locators. For more complicated logic, program it in Java. See the debate in comments in sqa.stackexchange.com/questions/27978/… Jan 2, 2018 at 16:28

4 Answers 4

3

XPath is worst (least preferred) way to locate elements. See What makes a good Selenium locator

When I do not have a good unique name/CSS locator, I often get a list, and loop over it (using programming language, not XPath expression) to select the desired element by some other attributes. XPath is flaky, can change after very minor design change.

This allows me to:

  • use more stable locators,
  • avoid spending time to debug complicated XPath expressions (I prefer to debug loops in real programming language, which I already mastered, so it is much quicker to write),
  • select elements in a way hard to express in XPath.
5
  • As long as you using the ID for element selection, does it make any difference if you are using xpath or css? Dec 29, 2017 at 23:57
  • Peter, how does the looping over a collection of elements will help in this given situation? Dec 30, 2017 at 0:01
  • @VishalAggarwal - OP said that ID is dynamic (changes every time). When you use non-unique locator, you will get a list of located elements. Dec 31, 2017 at 17:51
  • Peter, OP is trying to click a button whose ID may be dynamic but button label would be unique. Dec 31, 2017 at 19:44
  • @VishalAggarwal - If label is unique, we are all set of course. But how do you know if button label is unique? And what if label is dynamic too? Jan 1, 2018 at 17:13
1

Just simplifying MivaScott answer, Use button Label.

By.xpath("//button[contains(text(),'Confirm')]")
1
  • I couldn´t use label button, because the first problem is that the title in html is the same for both buttons and another problem is that button which I need hasn´t label on the page( so I coudn´t use something like by linktext or contains text)but it´s contain img some similarly like this google.cz/…: Jan 2, 2018 at 13:03
0

XPath gets a bad rap as it can be very fragile/brittle; any little change in the UI and it all goes to pot.

However, with the lack of good class names and IDs, XPath can be the only option. As another answer suggests, you can try making a list of all the similar elements and iterate through them until you find the right element. But that seems overkill if you're just talking about two buttons.

I'd go with the text()[contains()] route to identify each.

driver.findElement(By.xpath("//*[@id='dynamic-1']/span/button[text()[contains(.,'Save')]]"));

Do something like this for each (obviously with accurate xpathing).

0

Problem might be that you are using only ID to check the element. This is in most cases the best and ultimate way of finding element. Nonetheless, in your case you are not using the whole ID, so there might be more elements meeting that condition.

In this case you can do one of these:

  • Rely on the text (or some other attribute – for example find bigger element using size) as MivaScott and Vishal Aggarwal suggested.
  • Check parent WebElement from the selected one (using ".." in xpath). This may differ in element you are trying to reach and element that is causing you this trouble.
  • Do not use ID, but rather use identifier of parent element and then select the element you want to use from this element.

I don't understand the "hateful" comments about XPATH. XPATH used in OP's example is not some crazy XPATH (where "hateful" comments would apply), it is just xpath containing ID (In my opinion, using xpath for "contains" or "startswith" when dealing with IDs is in many cases a good thing).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.