This button is formed using button tag :


This button is formed using input tag :


This button is formed using title attribute :

Selenium webdriver Custom Locator

Sometimes we may want to write our own custom locators to access the elements in selenium webdriver. WebDriver’s API offers currently eight locators 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 new team member to learn xpath and CSS, also I want to minimize the time for write them.

If a fresher [zero experience] on this tool comes into selenium we have spend 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 element with 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 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 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 parameter


							public static By buttonText(String buttonText)
							


2.1. If return type is not By class, then WebElement interface will not consider the method as 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 it calls the findElements method By passing the WebDriver object as 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 Selenium 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 button 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 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 donot 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 constructor should accept the button text as String parameter.

3. Override the findElements method

based your need (like logging, getting size...)

4. Return the elements found in findElements method, findElement 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 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 writing a method which will find the element using title attribute (also known as tooltip), we have 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 method called buttonTitle which should accept title of the button as 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 used them lets see one example 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 donot 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 came 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 frame

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

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

If 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 unlimited number of locators, 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 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 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 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 second locator and goes on.

Finding element continues till it finds the element or there is 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 :


About Author

Myself KarthiQ, I am the author of this blog, I know ways to write a good article but some how I donot have the skills to make it to reach people, would you like help me to reach more people By sharing this Article in the social media.

Share this Article Facebook
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
  • Recent Addition

    new tutorial Registrations for Selenium Online Training is Over.

    Below are the training details:
    Meeting link : https://zoom.us/j/737840591
    Starting Time : 9:00PM 18th DEC 2018
     
    Join My Facebook Group
    Join Group