This topic is very important while writing test cases. Many things which developer develops are based on an ‘array’ and ‘for loops’. For e.g. when we search for any job on naukari.com, the output shown is always dynamic i.e. the output will never be fixed.
Sometimes it may happen that we may have very long xpath right from the root of Dom i.e. from ‘html’ tag then our code lost readability and maintenance issue arises if anything is changed in our page.
Those who find it very difficult to locate element by using dynamic xpath there various tools are available in the market for getting dynamic xpath. One of it is webdriver element locator.
You can try adding this plugin into firefox.
If we want to generate it programmatically then we need to see some patterns. Just to summarize, we will start from basics of Xpath.
XPath is defined as XML path. It is a syntax or language for finding any element on the web page using XML path expressions. XPath is used to find the location of any element on a web page using HTML DOM structure.
Absolute XPath
Relative XPath
It is the direct way to find the element, but the disadvantage of the “absolute XPath” is that if there are any changes made in the path of the element then that particular XPath gets failed.
The key characteristic of XPath is that it begins with the single forward slash (/) which means Dynamic XPATH you can select the element from the root node. Below is the example of an “absolute XPath” expression of the element shown in the below screen.
html/body/div[1]/section/div[1]/div/div/div/div[1]/div/div/ div/div/div[3]/div[1]/div/h4[1]/b
Example:
If the Path we defined is as follows:
html/head/body/table/tbody/tr/th
If there is a tag that has been added between body and table as shown below.
html/head/body/form/table/tbody/tr/th
The first path will not work as ‘form’ tag is added in between.
A ‘relative xpath’ is one where the path starts from the node of your choice i.e. it doesn't need to start from the root node.
It starts with Double forward slash (//)
Syntax: //table/tbody/tr/th
The advantage of using relative xpath is that you don’t need to mention the long xpath instead you can start from the middle or from between.
The disadvantage here is that
It will take more time in identifying the element as we specify the partial path and not exact path.
If there are multiple elements in the same path then it will select the first element which has been identified.
Now to generate dynamic xpath we need to see XPATH AXES.
XPath has a total of 13 different axes, which we will look at in this section. An XPath axes tells the XPath processor, which “direction” to head in as it navigates around the hierarchical tree of nodes.
self | Which contains only the context node |
ancestor | contains the ancestors of the context node, That is, the parent of the context node, its parent, etc., if it has one. |
ancestor-or-self | contains the context node and its ancestors |
attribute | contains all the attribute nodes, if any, of the context node |
child | contains the children of the context node |
descendant | contains the children of the context node, the children of those children, etc. |
descendant-or-self | contains the context node and its descendants |
following | contains all nodes which occur after the context node, in document order |
following-sibling | Selects all siblings after the current node |
namespace | contains all the namespace nodes, if any, of the context node |
parent | Contains the parent of the context node if it has one |
preceding | contains all nodes which occur before the context node, in document order |
preceding-sibling | contains the preceding siblings of the context node |
XPath contains the path of the element situated on the web page. Standard syntax for creating XPath is:
Xpath = //tagname [@attribute=’value’]
//: Selects the current node.
Tagname: Tagname of the particular node.
@: Selects the attribute.
Attribute: Attribute name of the node.
Value: Value of the attribute.
We need to follow some functions for this, which is as mentioned below:
The XPath expression selects nodes or a list of nodes on the basis of attributes like ID, Name, Classname etc from the XML document as illustrated below:
Xpath=//input[@name=’uid’]
Some more basic xpath expressions:
Xpath=//input[@type=’text’]
Xpath=//label[@id=’message23’]
Xpath=//input[@value=’RESET’]
‘contains()’ is a method used in XPath expressions. It is used when the value of any attribute changes dynamically, for example, login information on any page.
In the below XPath expression partial value ‘sub’ is used in place of a submit button. It can be observed that the element is successfully found.
Complete value of ‘Type’ is ‘submit’ but using only partial value ‘sub’.
Xpath=//*[contains(@type,’sub’)]
Complete value of ‘name’ is ‘btnLogin’ but using only partial value ‘btn’.
Xpath=.//*[contains(@name,’btn’)]
Similarly, in the below expression, we have taken the ‘id’ as an attribute and ‘message’ as its partial value. This will check 2 elements (‘User-ID must not be blank’ & ‘Password must not be blank’) as its ‘name’ attribute begins with ‘message’.
Xpath=//*[contains(@id,’message’)]
Xpath=//*[contains(text(),’here’)]
Xpath=//*[contains(@ href,’javabykiran.com’)]
In OR expression, two conditions are used, either 1st condition OR 2nd condition should be true. It is also applicable if either of the two conditions is true or both which means any one condition should be true in oder to find the element.
Xpath=//*[@type=’submit’ OR @name=’btnReset’]
“Start-with” function finds the element whose attributes value changes on refresh or any operation on the web page. In this expression, match the starting text of the attribute which is used to find the element whose attribute changes dynamically. You can also find the element whose attributes value is static (i.e. which does not change).
For example: Suppose the ID of particular element changes dynamically like as that of naukari.com search job checkbox.
id=”job12” id=”job 345” id=”job 8769”
And so on.. But the initial text remains the same. In this case, we use Start-with expression.
Xpath = //label[starts-with(@id,’message’)]
In this expression, with “text()” function, we find the element with exact text match as shown below. In our case, we find the element with text/id “UserID”.
Xpath = //td[text()=’UserID’]
Now we will discuss about XPATH axis, which we have seen in table given in XPath Axes section. Few are discussed here.
Selects all elements in the document of the current node( ) [here UserID input box is the current node] as shown below,
Xpath = //*[@type=’text’]//following::input
There are 3 “input” nodes matching by using “following” axis- password, login and sign in button. If you want to focus on any particular element, then you can use the below XPath method:
Xpath = //*[@type=’text’]//following::input[1]
Selects all nodes that come before the current node as shown below.
In the below expression, it identifies all the input elements before “LOGIN” button that is Userid and password input element.
Xpath = //*[@type=’submit’]//preceding::input
Selects the following siblings of the context node. Siblings are at the same level of the current node as shown below. It will find the element after the current node.
xpath = //*[@ type=’submit’]//following-sibling::input
Refer below code of testng and selenium for a complete example of dynamic Xpath. Here website which has been referenced is http://www.javabykiran.com/selenium/demo/
package com.jbk;
//import java.sql.Driver;
import java.util.List;
import java.util.concurrent.TimeUnit;
//import org.junit.runners.Parameterized.Parameters;
//import org.apache.bcel.generic.Select;
import org.openqa.selenium.Alert;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.support.ui.Select;
import org.testng.Assert;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.Test;
public class Login_TestCase{
public static WebDriver driver;
@BeforeSuite(groups = "Smoke")
public static WebDriver setup_Browser() throws Exception {
driver = new FirefoxDriver();
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
driver.get("file:///F:/offline%20website/index.html");
return driver;
}
@Test(priority = 1, groups = "Regression", description="To Check Project URL is Correct:")
public static void Verify_Url() {
// Actual url
String my_url = driver.getCurrentUrl();
System.out.println("page title is " + my_url);
// expected url
String expected_url = "file:///F:/offline%20website/ index.html";
Assert.assertEquals(my_url, expected_url);
System.out.println("**************************");
System.out.println("Test Case One with Thread Id:- "
+ Thread.currentThread().getId());
}
@Test(priority = 2, groups = "Regression", description="To verify Application Title: ")
public void verifyApplicationTitle() {
// Actual title
String my_title = driver.getTitle();
System.out.println("page title is " + my_title);
System.out.println("..........");
// expected title
String expected_title = "AdminLTE 2 | Log in";
Assert.assertEquals(my_title, expected_title);
System.out.println("************************");
System.out.println("Test Case two with Thread Id:- "
+ Thread.currentThread().getId());
}
@Test(priority = 3, groups = "Regression", description="")
public void verify_Title() {
String stitle = driver.findElement(By.xpath("//a[@href='index2. html']")).getText();
String exp = "AdminLTE"; Assert.assertEquals(stitle, exp);
System.out.println("Application title verify " + stitle);
System.out.println("**********************");
}
// start Log In Session
@Test(priority = 4, groups = "Regression")
public void loginsession() {
driver.findElement(By.xpath("//p[contains(text(),'Sign in to start your session')]"));
System.out.println("Sign in to start your session");
System.out.println("***********************");
}
@Test(priority = 5, groups = "Regression")
public void Check_PlaceHolder_Username() {
String str = driver.findElement(By.id("email")).getAttribute("placeholder");
String exp = "Email";
Assert.assertEquals(str, exp);
System.out.println("placeholder Email-verified");
System.out.println("*******************");
}
@Test(priority = 6, groups = "Regression")
public void Check_PlaceHolder_Password() {
String str = driver.findElement(By.xpath("//input[@id='password']")).getAttribute("placeholder");
String exp = "Password"; Assert.assertEquals(str, exp);
System.out.println("placeholder password- verified");
System.out.println("*******************");
}
@Test(priority = 7, groups = "Regression")
public void check_Button_color() {
WebElement signbtn = driver.findElement(By.xpath("//button[@ class='btnbtn-primary btn-block btn-flat']"));
System.out.println("befor mouse over button color is "+ signbtn.getCssValue("background-color"));
Actions act = new Actions(driver);
act.moveToElement(signbtn).build().perform();
System.out.println("after mouse over button color "
+ signbtn.getCssValue("color"));
System.out.println("*******************");
}
@Test(priority = 8, groups = "Regression")
public void check_Links() {
List< WebElement > links = driver.findElements(By.tagName("a"));
System.out.println(links.size());
System.out.println(".........");
for (inti = 0; i < links.size(); i++) {
System.out.println(links.get(i).getText());
}
}
@Test(priority = 9, groups = "Regression")
public void blank_username_password() {
WebElement stract = driver.findElement(By.xpath("//input[@type='text']"));
stract.sendKeys("");
String strexp = "sa";
Assert.assertNotEquals(stract, strexp);
WebElement passact = driver.findElement(By.xpath("//input[@ id='password']"));
passact.sendKeys("");
String passexp = "sa";
driver.findElement(By.xpath("//button[@class='btnbtn- primary btn-block btn-flat']")).click();
Assert.assertNotEquals(passact, passexp);
String uname = driver.findElement(By.xpath("//div[@ id='email_error']")).getText();
System.out.println(uname);
String password = driver.findElement(By.xpath("//div[@ id='password_error']")).getText();
System.out.println(password); System.out.println(". ");
}
@Test(priority = 10, groups = "Regression")
public void invalidusername_password() throws InterruptedException {
WebElement stract = driver.findElement(By.id("email"));
stract.sendKeys("kiran12@gmail.com");
String strexp = "kiran@gmail.com";
Assert.assertNotEquals(stract, strexp);
Thread.sleep(2000);
stract.clear();
WebElement passact = driver.findElement(By.id("password"));
passact.sendKeys("12345");
Thread.sleep(2000);
passact.clear();
String passexp = "123456";
Assert.assertNotEquals(passact, passexp);
driver.findElement(By.xpath("//button[@class='btnbtn-primary btn-block btn-flat']")).click();
System.out.println("Please enter email as kiran@gmail.com");
System.out.println("Please enter password 123456");
System.out.println("..........");
}
@Test(priority = 11, groups = "Regression")
public void validUsername_Password() throws InterruptedException {
driver.findElement(By.xpath("//input[@id='email']")).sendKeys("kiran@gmail.com");
driver.findElement(By.xpath("//input[@id='password']")).sendKeys("123456");
driver.findElement(By.xpath("//button[@class='btnbtn-primary btn-block btn-flat'])).click();
System.out.println("Online");
System.out.println("............");
}
@Test(priority = 12, groups = "Smoke")
public static void Verify_Url_DashBoard() {
// Actual url
String my_url = driver.getCurrentUrl();
System.out.println("page title is " + my_url);
// expected url
String expected_url = "file:///F:/offline%20website/ pages/examples/dashboard.html";
Assert.assertEquals(my_url, expected_url);
System.out.println("**************************");
}
@Test(priority = 13, groups = "Smoke")
public void verifyApplicationTitle_DashBoard() {
// Actual title
String my_title = driver.getTitle();
System.out.println("page title is " + my_title);
System.out.println("...........");
// expected title
String expected_title = "AdminLTE 2 | Dashboard";
Assert.assertEquals(my_title, expected_title);
System.out.println("************************");
}
@Test(priority = 14, groups = "Smoke")
public void heading_Dashboard() throws InterruptedException {
String stitle = driver.findElement(
By.xpath("//h1[contains(text(),'Dashboard')]")).getText();
String exp = "Dashboard Control panel";
Assert.assertEquals(stitle, exp);
System.out.println("Application title verify " + stitle);
System.out.println("**********************");
Thread.sleep(2000);
}
@Test(priority = 15, groups = "Unit")
public void click_OnUser() throws InterruptedException {
driver. findElement(By.xpath("//a[@href='users. html']")).click();
Thread.sleep(2000);
driver.findElement(By.xpath("//span[@class='labellabel-danger']")).click();
// click on 1St delete button @SuppressWarnings("unused")
Alert alt = driver.switchTo().alert();
System.out.println(driver.switchTo().alert().getText());
driver.switchTo().alert().accept();
}
@Test(priority = 16, groups = "Unit")
public void getTableData() throws InterruptedException {
WebElement Table = driver.findElement(By.xpath("//table[@ class='table table-hover']"));
List< WebElement >tr =Table.findElements(By.tagName("tr"));
System.out.println("total no of rows " + tr.size());
for (WebElement row : tr) {
List< WebElement > td = row.findElements(By.tagName("td"));
for (WebElement col : td) {
System.out.println(col.getText());
}
System.out.println(".........");
}
Thread.sleep(2000);
}
@Test(priority = 17, groups = "Unit")
public void Click_On_AddUser_Btn() throws InterruptedException {
driver.findElement(By.xpath("//button[@class='btnbtn-block btn-primary btn-sm pull-right']")).click();
Thread.sleep(2000);
}
@Test(priority = 18, groups = "Unit")
public void Fill_Form() throws InterruptedException {
WebElement uname = driver.findElement(By.xpath("//input[@ id='username']"));
uname.sendKeys("Akshay");
Thread.sleep(2000);
WebElement mobile = driver.findElement(By.xpath("//input[@id='mobile']"));
mobile.sendKeys("8605218926");
Thread.sleep(2000);
WebElement email = driver.findElement(By.xpath("//input[@id='email']"));
email.sendKeys("akshay@gmail.com");
Thread.sleep(2000);
WebElement gender = driver.findElement(By.xpath(".//*[@id='Male']"));
gender.click();
Thread.sleep(2000);
WebElement we = driver.findElement(By.xpath("//select[@class='form- control']"));
Select s = new Select(we);
s.selectByVisibleText("Maharashtra");
WebElement password = driver.findElement(By.xpath("//input[@ id='password']"));
password.sendKeys("Akshay");
Thread.sleep(2000);
driver.findElement(By.xpath("//button[@id='submit']")).
submit();
Thread.sleep(2000);
@SuppressWarnings("unused")
Alert alt2 = driver.switchTo().alert();
Thread.sleep(1000);
System.out.println(driver.switchTo().alert().getText());
driver.switchTo().alert().accept();
}
@Test(priority = 19, groups = "Unit")
public void clickOn_OperatorBtn() throws InterruptedException {
driver.findElement(By.xpath("//span[text()='Operators']")).click();
Thread.sleep(3000);
// Get Operator table Data
//driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
WebElement Table1 = driver.findElement(By.xpath("//table[@ class='table table-hover']"));
List< WebElement >tr1=Table1.findElements(By.tagName("tr"));
System.out.println("total no of rows " + tr1.size());
for (WebElement row1 : tr1) {
List< WebElement > td1 = row1.findElements(By.tagName("td"));
for (WebElement col1 : td1) {
System.out.println(col1.getText());
}
System.out.println("........");
}
Thread.sleep(2000);
}
@Test(priority = 20, groups = "Unit") public void logOutBtn() {
driver.findElement(By.xpath("//a[text()='LOGOUT']")).click();
System.out.println(driver.findElement(By.xpath("//p[contains(text(),'Logout successfully')]")).getText());
}
@AfterSuite(groups = "Smoke")
public void close_Browse() {
driver.close();
}
}