Is it possible to Identifying an object using multiple locators in Selenium?

4,152 views
Skip to first unread message

Sameer Uddin

unread,
Jul 7, 2014, 3:35:23 AM7/7/14
to seleniu...@googlegroups.com
Hi,

I am new to Selenium and want to know if there is any way to identify an object using multiple locators (xpath, id, name..etc) in Selenium.

Example:
While identifying an object, i want to give find by xpath OR find by id OR find by name...etc. If any of the locator values change, my test will still pass. Example, if first locator (here xpath) changes and selenium is unable to identify the object, , then it will look for next locator like id and so on and if any of the locators is successful in identifying the object, it will skip rest of teh locators for identifying that object and continues the test.

This will help in reducing the automation maintenance cost when any object properties change (like xpath, id...etc)

Waiting eagerly for reply.


Thanks & Regards,
Sameer

David

unread,
Jul 7, 2014, 6:04:36 PM7/7/14
to seleniu...@googlegroups.com
You'd have to build your own support for that in your test framework. An example is you pass in a list of identifiers/locators to the (custom) find method which will try finding each locator from first item in list and if found return the element and if fail (a catch in try/catch block), catch/ignore the failure and try next element in list until we hit the last one. If last one fails we then return the exception or a custom exception about all locators provided fail to find the element.

But the simpler method is to just use XPath or CSS selectors (either one, not both combined). Because both XPath and CSS provide options to define multiple locators as an XPath or CSS value. But you can't mix the two.

E.g. XPath =  "//div[text()='locator 1'] | //div[@class='alternate locator 2'] | id('alternate locator 3')"

e.g. CSS = "div[@value='locator 1'], #idValue2, .classValue3"

For XPath the pipe '|' symbol is your value separator, for CSS, it is a comma ","

Find by ID, name, tag name, link text don't have such multi value options.

Frass

unread,
Jul 8, 2014, 9:10:37 AM7/8/14
to seleniu...@googlegroups.com
Hi, in any case this will greatly increase maintenance because if I understand you correctly you are going to have to write the locator of each element (or object if you like) 3 - 4 times (for xpath/id/name etc) so I would surely advise against this.  You should just stick to using Css or Id, never use Xpath.

David

unread,
Jul 11, 2014, 6:52:06 PM7/11/14
to seleniu...@googlegroups.com
I wouldn't say not to use XPath. Sometimes elements are better defined or parameterized with XPath if you need to use node traversal (previous siblings or up the parent tree) or element text matching, all features that are lacking in CSS.

There is a case where multiple locators (via CSS or XPath) actually do come in handy - A/B testing. If you don't want/need to separate out the page objects, locators, and tests to have a version for flow A and one for flow B. You can handle it with single locator variables using multiple values so either one matching will function correctly with Selenium.

gilbertf

unread,
Jul 17, 2014, 10:59:19 AM7/17/14
to seleniu...@googlegroups.com
I would advise against having the normal flow of your tests go through exceptions.   Moreover, you can do this without getting exceptions thrown back at you by using findElements(By by).

The general flow would look like this:
List<WebElement> widgets= driver.findElements(By.className("widgetClass"));
 if(widgets.isEmpty())  //the widget has not been found
{
   widgets= driver.findElements(By.xpath("//xpathToWidget"));
  if(widgets.isEmpty())   //still not found
   { /*try again*/}
//etc, etc for all possible ways
}
if (!widgets.isEmpty()) //one of the ways worked
{/*do the rest of the test*/}
else {/*fail the test, the widget cannot be found*/}

This simple approach does not check if the expression matched more than one corresponding widget, but that can be added easily.

I used this trick to verify that no error messages appear after a form submit.

David

unread,
Jul 17, 2014, 2:12:04 PM7/17/14
to seleniu...@googlegroups.com
gilbertf, your sample code, that doesn't take into account the page object design does it?

If you incorporate the WebDriver code directly into test case like in the presented sample, then you could skip exceptions and fail the test via the test case like an assert that will fail when nothing matches. (or like return false instead of true and assertTrue agains the false result)

However, if you use page objects, you don't do asserts within the page object code. So in that case, you have 2 options. Return a state at end of test (e.g. false if not found) for th test to then assert against or throw an exception for the test to handle (catch it and present a different error message, don't catch and let exception kill the test, etc.). In the case of checking whether something exists (or is found) or not, returning false is good option. However, in cases where you perform actions like you click or type into element, and you check for variations of the locator such that as long as one matches you will use it for automation, for that, it doesn't always make sense to return false (or true) for a method that performs an action rather than check state/status. So in those cases, it is better to throw an exception rather than return false. Or in some cases, the method returns other values (String, integer, some object), so you can't add on returning false on fail to that in a conventional way, so throwing exception is better there too.

François-Léonard Gilbert

unread,
Jul 17, 2014, 3:27:04 PM7/17/14
to seleniu...@googlegroups.com

That code is pretty much location-agnostic; to make it work in a POD project it could be incorporated in the page object and made to throw a custom exception if all location efforts fail.
My point is that using that pattern does the minimum effort necessary to locate a widget like the OP wanted and shouldn't leak exceptions in normal conditions.  This makes test failures more salient and removes the temptation of using ugly "catch(Exception e)" statements.

--
You received this message because you are subscribed to a topic in the Google Groups "Selenium Users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/selenium-users/LgqQz4aTb00/unsubscribe.
To unsubscribe from this group and all its topics, send an email to selenium-user...@googlegroups.com.
To post to this group, send email to seleniu...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/selenium-users/211618c6-184f-487c-a4a3-0de9da371adb%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages