This button is formed using button tag :


This button is formed using input tag :


This button is formed using title attribute :

Selenium Custom Locator

Sometimes we may want to write our own custom locators to access the elements in selenium. WebDriver’s API offers eight locators currently, allowing to retrieve elements By id, name attribute, tag name, link text or partial link text, XPath, class name, and css selector.

However, those default locators not enough for us now, because we have to access the elements through a new attribute.

Yes, we can access those elements using the attributes present in the element either with XPath or CSS value. But I wanted my framework not to give burden on a new team member to learn XPath and CSS, also I want to minimize the time for writing them.

If a fresher [zero experience] on this tool comes into selenium we have spent hours to train him on XPath and CSS, So we want to write our Custom Locators to avoid these issues. We expect something like below, * refers to any operation after finding the element.


							driver.findElement(By.myLocator("locator value")).*
							

Or something like below


							driver.findElement(ByElementText("text value")).*
							

This way we can find an element with a custom attribute, Before we can create a custom locator let's understand the By class architecture, We can achieve custom locators By extending the By Class.

Custom By class : In selenium webdriver methods present in the By class are used to locate the element(s), all the methods present in the By class are static methods. We can access the static methods and static variables using Class Reference.

WebDriver’s API currently provides eight locators to retrieve elements By id, name attribute, tag name, link text or partial link text, XPath, class name, and CSS Selector. These locators are low level, but we can implement our own locators for high-level purpose

Button Text Locator : We will try to implement the custom locator to find a element based on the text present in the button We will consider the below HTML code for our experiment


							<button id='button1'>Alert Me</button>
							

We have to use below xpath to find the experiment element, and which requires good knowledge on xpath
//button[@text()='Alert Me']


							driver.findElement(By.xpath("//button[text()='Alert Me']")).*
							

Wouldn't it be easy if the user just can write locator like below with button text
Button text -> Alert Me


							driver.findElement(buttonText("Alert Me")).*
							

By Class has 8 type of locators and one abstract method which is findElements, So whoever extends the By class they must provide implementations for the findElements method. By default webdriver provides the implementation for the 'findElement' method so no need to override the 'findElement' method


							public abstract List<WebElement> findElements(SearchContext context);
							


1. Override By Class Constructor : Let's learn about how to implement the buttonText custom locator using By Class Constructor. 1. Create a Java class with a hint that it related with Locator ByButtonText

2. Create a method and name it as you new custom locator buttonText and set the return type as By, and this method should accept the button text as a parameter


							public static By buttonText(String buttonText)
							


2.1. If the return type is not By class, then the WebElement interface will not consider the method as a locator.

3. Implement the By class constructor also return it


							return new By(){...}
							


4. Override the findElements method, findElement method is not abstract method so no need to override the findElement method.


							@Override
							public List<WebElement> findElements(SearchContext arg0) {
							


5. Form the XPath based on the button text we received from the buttonText custom locator


							String xpath = "//button[text()='" + buttonText + "']";
							


6. When WebElement interface processes the By class constructor and it calls the findElements method By passing the WebDriver object as a parameter.

7. Use the call the actual findElements method from the driver object, and return the elements


							List<WebElement> elements = arg0.findElements(By.xpath(xpath));
							return elements;
							


Complete program for buttonText custom locator in webdriver


							import java.util.List;
							import org.openqa.selenium.By;
							import org.openqa.selenium.SearchContext;
							import org.openqa.selenium.WebElement;

							public class ByButtonText  {
								public static By buttonText(String buttonText)
								{
									return new By(){
										@Override
										public List<WebElement> findElements(SearchContext arg0) {
											String xpath = "//button[text()='" + buttonText + "']";
											List<WebElement> elements = arg0.findElements(By.xpath(xpath));
											 return elements;
										}
									};
								}
							}
							


Let's use the custom locator in actual use :
1. Open browser and Navigate to https://chercher.tech/java/custom-locators-selenium-webdriver

2. Get the number of buttons present with 'Alert Me' text and print it using buttonText custom locator.


							// get number of buttons using findElements with Custom Locator
							int noOfButtons = driver.findElements(ByButtonText.buttonText("Alert Me")).size();
							System.out.println("No. of Button : " +noOfButtons);
							


3. Click the Alert Me button using the text 'Alert Me' using buttonText custom locator


							// click the button using findElement with Custom Locator
							driver.findElement(ByButtonText.buttonText("Alert Me")).click();
							


Note : We have used the buttonText() method with class reference ByButtonText.buttonText, we can use just like buttonText if we static import the ByButtonText class


							import static custom.ByButtonText.*;
							


2. Implementing Class Constructor :
We can also implement the custom constructor using Implementing Class constructor, this method is only for your informational purpose and I do not suggest to use this method in your frameworks as it involves creating multiple objects using constructors

We can use this custom Locator to find element by attribute of the element in selenium, In this method instead, we will learn how to find the button using button value.

For your information button can be formed using button tag and input tag, first method deal with button tag. this method deals with button with input tag. When developers use input tag the attribute value's value will be the button text.


							<input type='button' value='Bingo'>
							


xpath for the above button tag will be //input[@type='button'][@value='Bingo']


							driver.findElement(By.xpath("//input[@type='button'][@value='Bingo']")).*
							


We want to ease the XPath to the automation script writers, So we would be expecting something like below. We can also say this as writing custom XPath with different locator name.


							driver.findElement(buttonValue("Bingo")).*
							

Steps to implement the Implementing Class Constructor :

  1. Create a Java class 'ByButtonValue' which should extend By class
  2. Create constructor of the custom locator class ByButtonValue and the constructor should accept the button text as a String parameter.
  3. Override the findElements method based on your need (like logging, getting size...)
  4. Return the elements found in findElements method, findElements method is already implemented in By class itself so no need to worry about it
  5. In this example, I have used Private variable 'buttonValue', because private variable or methods are not available outside the method.


							public class ByButtonValue extends By{
								private String buttonValue;
								public ByButtonValue(String buttonValue)
								{
									this.buttonValue = buttonValue;
								}

								@Override
								public List<WebElement> findElements(SearchContext context) 
								{
									 String xpath = "//inpput[@type='button'][@value='" + buttonValue + "']";
									 List<WebElement> elems = context.findElements(By.xpath(xpath));
									 return elems;
								}
							}
							


Actual Use of custom locator :
1. Open the browser and navigate to https://chercher.tech/java/custom-locators-selenium-webdriver

2. Get the number of buttons whose value attribute is 'Bingo'

3. Click the button By finding the button using the value attribute


							public static void main(String[] args) {
								// set the geckodriver.exe property
								System.setProperty("webdriver.gecko.driver", "C:/PATH/geckodriver.exe");
								// open firefox
								WebDriver driver = new FirefoxDriver();
								driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
								
								driver.get("https://chercher.tech/java/custom-locators-selenium-webdriver");
								
								// get number of buttons using findElements with Custom Locator
								int noOfButtons = driver.findElements(new ByButtonValue("Bingo")).size();
								System.out.println("No. of Button : " +noOfButtons);
								
								// click the button using findElement with Custom Locator
								driver.findElement(new ByButtonValue("Bingo")).click();	
							}
							

Custom Locator with Methods:

In this example we will be using simple methods to form the custom locator, but this method is not exactly a custom method but still this method is in very good usage.

We will write a method which will find the element using title attribute (also known as tooltip), we have a button called 'karthiQ' (my name) which has title attribute value as 'author'

Steps to implement Method based Custom Locator :

  • Create class to hold all the custom locator methods
  • Create a method called buttonTitle which should accept the title of the button as a String parameter.
  • Form the xpath/CSS inside the method and return it as By.xpath or By.CssSelector

							import org.openqa.selenium.By;
							public class ByMethods {
								public static By buttonTitle(String title){
									String xpath = "//input[@type='button'][@title='"+title+"']";
									
									// returned the xpath formed along with By Class
									return By.xpath(xpath);
								}
							}
							
Usage :

							public static void main(String[] args) {
								// set the geckodriver.exe property
								System.setProperty("webdriver.gecko.driver", "C:/PATH/geckodriver.exe");
								// open firefox
								WebDriver driver = new FirefoxDriver();
								driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
								
								driver.get("https://chercher.tech/java/custom-locators-selenium-webdriver");
								
								// get number of buttons using findElements with Custom Locator
								int noOfButtons = driver.findElements(ByMethods.buttonTitle("author")).size();
								System.out.println("No. of Button : " +noOfButtons);
								
								driver.findElement(ByMethods.buttonTitle("author")).click();
							}
							

Explore Not So familiar Locators in Selenium Webdriver

There are few more locators present in Selenium Webdriver, we might never use them lets see one example of how to use them

Below locator may look like same as the locator you have been using but these are static classes present in the By class. I do not think you need any explanations for below locators.

  • ById
  • ByName
  • ByTagName
  • ByClassName
  • ByLinkText
  • ByPartialLinkText
  • ByCssSelector
  • ByXPath

							<a id='idp' class='classp' name='namep' >Custom Locators</a>
							

Please find the example for the above locators


							driver.findElement(new ById("idp")).click();
							driver.findElement(new ByClassName("classp")).click();
							driver.findElement(new ByName("namep")).click();
							driver.findElement(new ByTagName("a")).click();
							driver.findElement(new ByLinkText("Custom Locators")).click();
							driver.findElement(new ByPartialLinkText("Custom")).click();
							driver.findElement(new ByCssSelector("a#p")).click();
							driver.findElement(new ByXPath("//a")).click();
							

Xpath in Selenium

ByIdOrName Locator in Selenium

There is a locator called ByIdOrName which helps selenium user to find element either by name or by id, we have already come across such concept do you remember. While handling the frames we can pass either id or name of the frame, internally frame uses this locator to match the frame

ByIdOrName locator is present under org.openqa.selenium.support package, to use this locator we have to call the constructor of the ByIdOrName class and pass the name or id.

This method tries to find the element using id first, it waits till the max wait time for the element if it is not able to find the element with id then only ByIdOrName locator tries with the name.

If the element is available with id then there will be no wait time and selenium will not check the element with name attribute at all.


								import java.util.concurrent.TimeUnit;
								import org.openqa.selenium.WebDriver;
								import org.openqa.selenium.firefox.FirefoxDriver;
								import org.openqa.selenium.support.ByIdOrName;

								public class SeleniumOtherPackages {
									public static void main(String[] args) {
										// set the geckodriver.exe property
										System.setProperty("webdriver.gecko.driver", "C:/PATH/geckodriver.exe");
										
										// open firefox
										WebDriver driver = new FirefoxDriver();
										driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
										
										driver.get("https://chercher.tech/java/custom-locators-selenium-webdriver");
										
										// pass either id or name
										driver.findElement(new ByIdOrName("namep")).click();
									}
								}
								

Headless browser in Selenium webdriver

Video tutorial for ByIdOrName Locator

Subscribe to my youtube channel :


ByChained locator in selenium

ByChained locator helps to find the element based on the parent element, it accepts an unlimited number of locators, The sequence is parent, child, grand child, great Grand child, target.


								new ByChained(By.....bys.)
								

Parent element comes first and then target element, In below HTML code we have two text input bars, both are formed with the same tagname. Save the HTML in your local machine


								<html>
								   <head></head>
								   <body>
									  Outer Textbar: <input id="outer" type="text"><br><br><br>
									  <div id="div">
										 Inner Textbar : <input id="inner" type="text"><br>
									  </div>
								   </body>
								</html>
								

If we use below ByChained locator, we will find the inner input bar for the above HTML code.


								new ByChained(By.id("div"), By.tagName("input"))
								


1. First, find the element with id 'div'
2. Finds the element with tagname 'input' which is inside the 'div' element that we found in the first step Simple program for using ByChained locator in selenium


								public class ByChainedLocator {
									public static void main(String[] args) {
										// set the geckodriver.exe property
										System.setProperty("webdriver.gecko.driver", "C:/PATH/geckodriver.exe");
										
										// open firefox
										WebDriver driver = new FirefoxDriver();
										driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
										
										driver.get("file:///path/a.html");
										
										// pass either id or name
										driver.findElement(new ByChained(By.id("div"), By.tagName("input"))).sendKeys("ChereCher Tech");;
									}
								}
								
by-chained-locator-selenium-webdriver

Video tutorial for ByChained Locator

Subscribe to my youtube channel :


ByAll Locator in selenium

ByAll locator in selenium helps to find the element based on the given locators, locator could be any other types like id, name, classname, link text, xpath, css, partial link text.

ByAll locator tries to find the element using the first locator if the element is not present then it waits for given implicit wait time, once it reaches the maximum wait time and if there is no element, ByAll method tries to find the element using the second locator and goes on.

Finding element continues till it finds the element or there are no more locators


								public static void main(String[] args) {
									// set the geckodriver.exe property
									System.setProperty("webdriver.gecko.driver", "C:/PATH/geckodriver.exe");
									
									// open firefox
									WebDriver driver = new FirefoxDriver();
									driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
									
									driver.get("file:///C:/PATH/a.html");
									
									// find based on given locators
									driver.findElement(new ByAll(By.className("not-exist"), By.id("inner"))).sendKeys("help");
								}
								

You may like our Selenium Locators chapter as well, so try reading : Selenium Standard Locators

Video tutorial for ByAll Locator

Subscribe to my youtube channel :


Comment / Suggestion Section
Point our Mistakes and Post Your Suggestions
  • Atitkumar Shingatalur
    Hi karthik,
    Your articles are very helpful, and are very easy to understand. 
    I appreciate your good work. 
    Reply
    • karthiQ [ admin]
      Hi Atitkumar Shingatalur ,
      
      We are glad that you like it
      Reply
  • Suhi
    Hi Karthik,
    Very informative tutorial. You have covered topics like custom locator and other  find by elements which is not shared in other selenium tutorial websites. Keep up the good work
    Thanks
    Reply
    • karthiQ [admin]
      Thanks, Suhi. for your feedback
      Reply
  • Manish Shridhar
    It was a new session
    Reply
  • Umidakhon Gulyamova
    Reply