Showing posts with label Selenium WebDriver. Show all posts
Showing posts with label Selenium WebDriver. Show all posts

Data Driven Framework Part 2

Data driven example with excel sheet - Please refer below source codes to understand the implementation of Data Driven Testing/Framework using excel sheet.

In this example we are passing the username and password using excel sheet to test the login functionality.

Excel Sheet with user credentials:

Base Class: In this base class we have created following methods

setup() - to launch the browser and navigate to application
tearDown() - quit the browser
getExcelData() - to get the excel test data and store using 2-D Array.
and we have created the object of NewExcelLibrary to use the different methods to access the excel sheet. Complete excel library you can find here.
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
import com.utility.NewExcelLibrary;

public class BaseClass {
 public WebDriver driver;
 NewExcelLibrary obj= new NewExcelLibrary("D:\\Workspace_Eclipse\\DataDriven\\TestData\\User.xlsx");
 
 @BeforeMethod
 public void setup() {
  System.setProperty("webdriver.chrome.driver",
    "C:\\Users\\Hitendra\\Downloads\\chromedriver_win32 (2)\\chromedriver.exe");
  driver = new ChromeDriver();
  driver.manage().window().maximize();
  driver.get("https://opensource-demo.orangehrmlive.com/");
 }

 @AfterMethod
 public void tearDown() {
  driver.quit();
 }
 
 @DataProvider(name ="Credentials1")
 public Object[][] getExcelData() {
  //Totals rows count
  int rows=obj.getRowCount("Data");
  //Total Columns
  int column=obj.getColumnCount("Data");
  int actRows=rows-1;
  
  Object[][] data= new Object[actRows][column];
  
  for(int i=0;i<actRows;i++) {
   for(int j=0; j<column;j++) {
    data[i][j]=obj.getCellData("Data", j, i+2);
   }
  }
  return data;
 }
}

TestClass: Supply the dataProvider name in test method

import org.openqa.selenium.By;
import org.testng.Assert;
import org.testng.annotations.Test;
import com.base.BaseClass;

public class DataDrivenTest extends BaseClass {

 @Test(dataProvider = "Credentials1")
 public void loginTest(String username,String password) {
  
  driver.findElement(By.id("txtUsername")).sendKeys(username);
  driver.findElement(By.id("txtPassword")).sendKeys(password);
  driver.findElement(By.id("btnLogin")).click();
  String actualURL=driver.getCurrentUrl();
  String expectedURL="https://opensource-demo.orangehrmlive.com/index.php/dashboard";
  Assert.assertEquals(actualURL, expectedURL);
 }
}

Output: Refer the below output, you can see our test executed with different set of test data

Please refer below YouTube video to understand better.

Data Driven Framework Part 1

What is Data Driven Testing?

Data-driven is a test automation framework which stores test data in a table or spreadsheet format. This allows automation engineers to have a single test script which can execute tests for all the test data in the table.


Why Data Driven Testing?

Example 1:
We want to test the login system with multiple input fields with 100 different data sets.
To test this, you can take following different approaches:
Approach 1) Create 100 scripts one for each dataset and runs each test separately one by one.
Approach 2) Manually change the value in the test script and run it several times.
Approach 3) Import the data from the excel sheet. Fetch test data from excel rows one by one and execute the script.
In the given three scenarios first two are laborious and time-consuming. Therefore, it is ideal to follow the third approach.
Thus, the third approach is nothing but a Data-Driven framework.

Example 2: Test different products in e-commerce application.

Advantages of Data Driven Framework
  • Advantages of using Data Driven Test Framework
  • Re-usability of code
  • Improves test coverage
  • Faster Execution
  • Less maintenance
  • Permits better error handling
How to Implement?

Using DataProvider in TestNG
An important features provided by TestNG is the testng DataProvider feature. It helps you to write data-driven tests which essentially means that same test method can be run multiple times with different data-setsTo test this.

To use the DataProvider feature in the tests, you have to declare a method annotated by @DataProvider and then use the said method in the test method using the ‘dataProvider‘ attribute in the @Test annotation.
Data provider returns a two-dimensional JAVA object and test method will invoke M times in a M*N type of object array. 

Lets have a look Data driven example without using excel sheet just to understand the data driven test --  Data driven testing of login functionality.

Base Class: In this base class we have created following methods

setup() - to launch the browser and navigate to application
tearDown() - quit the browser
getData() - to setup the test data using 2-D Array.
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
import com.utility.NewExcelLibrary;

public class BaseClass {
 public WebDriver driver;
 NewExcelLibrary obj= new NewExcelLibrary("D:\\Workspace_Eclipse\\DataDriven\\TestData\\User.xlsx");
 
 @BeforeMethod
 public void setup() {
  System.setProperty("webdriver.chrome.driver",
    "C:\\Users\\Hitendra\\Downloads\\chromedriver_win32 (2)\\chromedriver.exe");
  driver = new ChromeDriver();
  driver.manage().window().maximize();
  driver.get("https://opensource-demo.orangehrmlive.com/");
 }

 @AfterMethod
 public void tearDown() {
  driver.quit();
 }

 @DataProvider(name = "Credentials")
 public Object[][] getData() {

  Object[][] data = new Object[3][2];

  data[0][0] = "admin";
  data[0][1] = "admin123";

  data[1][0] = "admin1";
  data[1][1] = "admin123";

  data[2][0] = "admin2";
  data[2][1] = "admin";

  return data;
 }
}

Test Class: Supply the dataProvider name in test method
import org.openqa.selenium.By;
import org.testng.Assert;
import org.testng.annotations.Test;
import com.base.BaseClass;

public class DataDrivenTest extends BaseClass {

 @Test(dataProvider = "Credentials")
 public void loginTest(String username,String password) {
  
  driver.findElement(By.id("txtUsername")).sendKeys(username);
  driver.findElement(By.id("txtPassword")).sendKeys(password);
  driver.findElement(By.id("btnLogin")).click();
  String actualURL=driver.getCurrentUrl();
  String expectedURL="https://opensource-demo.orangehrmlive.com/index.php/dashboard";
  Assert.assertEquals(actualURL, expectedURL);
 }
}

Output: Refer the below output, you can see our test executed with different set of test data
Please refer the below YouTube video to understand better:

How to write data into Excel file

Below is the code to write data into excel sheet:

Library class to write data into excel sheet
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

public class WriteExcel {
 
 public void writeExcel(String sheetName, String cellvalue, int row, int col) throws Exception {
  
  String excelPath="D:\\Workspace_Eclipse\\ReadExcel\\TestData\\TestData.xlsx";
  
  File file= new File(excelPath);
  
  FileInputStream fis= new FileInputStream(file);
  
  XSSFWorkbook wb= new XSSFWorkbook(fis);
  
  XSSFSheet sheet= wb.getSheet(sheetName);
  
  sheet.getRow(row).createCell(col).setCellValue(cellvalue);
  
  FileOutputStream fos= new FileOutputStream(new File(excelPath));
  
  wb.write(fos);
  
  wb.close();
  
  fos.close();
 }
}

Sample Test Class
import org.testng.annotations.Test;
import com.writeExcel.WriteExcel;

public class WriteExcelTest {

 WriteExcel obj= new WriteExcel();
 
 @Test
 public void writeExcelTest() throws Exception {
  obj.writeExcel("Test", "Male", 0, 2);
 }
 
 @Test
 public void writeExcelTest1() throws Exception {
  obj.writeExcel("Test", "Female", 1, 2);
 }
 
}

Please refer below YouTube video on how to write data into excel sheet

Read excel file in Selenium using Apache POI

How to Read/Write Excel File?
  • To Read and Write excel files in Selenium we have to take help of third party API like JXL and Apache POI.
  • To read or write an Excel,Apache provides a very famous library POI. This library is capable enough to read and write both XLS and XLSX file format of Excel.
Difference between JXL and Apache POI
  • Most significant difference is that Java JXL does not support ".xlsx" format; it only supports ".xls" format.
  • JXL doesn't support Conditional Formatting, Apache POI does.
  • JXL doesn't support rich text formatting, i.e. different formatting within a text string.
Different Classes and Interfaces in Apache POI:
Classes and Interfaces
Explanation of classes and interfaces POI for reading XLS and XLSX file
  • Workbook: XSSFWorkbook and HSSFWorkbook classes implement this interface.
  • XSSFWorkbook: Is a class representation of XLSX file.
  • HSSFWorkbook: Is a class representation of XLS file.
  • Sheet: XSSFSheet and HSSFSheet classes implement this interface.
  • XSSFSheet: Is a class representing a sheet in an XLSX file.
  • HSSFSheet: Is a class representing a sheet in an XLS file.
  • Row: XSSFRow and HSSFRow classes implement this interface.
  • XSSFRow: Is a class representing a row in the sheet of XLSX file.
  • HSSFRow: Is a class representing a row in the sheet of XLS file.
  • Cell: XSSFCell and HSSFCell classes implement this interface.
  • XSSFCell: Is a class representing a cell in a row of XLSX file.
  • HSSFCell: Is a class representing a cell in a row of XLS file.
Download Apache POI Jars and configure in your project to work with excel.
1. If you are using plain java project then download the jars from below link and configure in your project's build path.
http://poi.apache.org/download.html
2. And if you are using maven use below dependencies in your POM.xml file.
                        <dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>

We have a excel file in project directory and it contains below data:

Please refer below program to read above excel file in selenium:
import java.io.File;
import java.io.FileInputStream;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.testng.annotations.Test;

public class ReadExcel {
 
 @Test
 public void readExcel() throws Exception {
  
  String excelPath="D:\\Workspace_Eclipse\\ReadExcel\\TestData\\TestData.xlsx";
  String fileName="TestData";
  String sheetName="Test";
  //Create the object of File Class to get the excel path
  File file= new File(excelPath);
  //To read the file
  FileInputStream fis= new FileInputStream(file);
  XSSFWorkbook wb= new XSSFWorkbook(fis);
  XSSFSheet sheet=wb.getSheet(sheetName);
  //Get Total Rows in Excel Sheet
  int rowCount=sheet.getLastRowNum();
  System.out.println("Total Rows: "+(rowCount+1));
  //Print a particular cell value
  String data=sheet.getRow(0).getCell(1).getStringCellValue();
  System.out.println("Particular cell value: "+data);
  
  //Loop to print all values of the excel sheet
  for(int i=0; i<=rowCount;i++) {
   Row row=sheet.getRow(i);
   for(int j=0; j<row.getLastCellNum();j++) {
    String data1=sheet.getRow(i).getCell(j).getStringCellValue();
    System.out.print(data1+" ");
   }
   System.out.println();
  }
  wb.close();
 }
}

Output:
[RemoteTestNG] detected TestNG version 6.14.3
Total Rows: 10
Particular cell value: LastName1
FirstName1 LastName1 
FirstName2 LastName2 
FirstName3 LastName3 
FirstName4 LastName4 
FirstName5 LastName5 
FirstName6 LastName6 
FirstName7 LastName7 
FirstName8 LastName8 
FirstName9 LastName9 
FirstName10 LastName10 
PASSED: readExcel

How to create Excel Library so that we can use it inside out test cases. For that please refer below program.

Excel Library class:
import java.io.File;
import java.io.FileInputStream;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

public class ExcelLibrary {
 
 XSSFWorkbook wb;
 XSSFSheet sheet;
 //Below Constructor is to load the excel configuration 
 public ExcelLibrary() throws Exception {
  String excelPath="D:\\Workspace_Eclipse\\ReadExcel\\TestData\\TestData.xlsx";
  File file= new File(excelPath);
  FileInputStream fis= new FileInputStream(file);
  wb= new XSSFWorkbook(fis);
 }
 public String readData(String sheetName, int row, int col) {
  sheet=wb.getSheet(sheetName);
  String data=sheet.getRow(row).getCell(col).getStringCellValue();
  return data;
 }
}

TestClass:
import org.testng.annotations.Test;
import com.readExcel.ExcelLibrary;

public class ReadExcelTest {
 
 @Test
 public void readExcelTest() throws Exception {
  ExcelLibrary obj= new ExcelLibrary();
  //Call readData method from ExcelLibrary class to get the value of Particular cell
  String datString=obj.readData("Test", 5, 1);
  System.out.println("The data is: "+datString);
 }
}

Please refer below YouTube video to get more details:

Page Object Model (POM) using Page Factory in Selenium

In last post we have seen Page Object Model with basic approach, in this post we will see Page Object Model using Page Factory in Selenium.

What is PageFactory?
PageFactory Class in Selenium is an extension to the Page Object design pattern. It is used to initialize the web elements of the Page. It is used to initialize elements of a Page class without having to use 'FindElement' or 'FindElements'.

Here we follow the below steps to implement Page Object Model using Page Factory:

POM.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>POMPageFactory</groupId>
  <artifactId>POMPageFactory</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <dependencies>
  <dependency>
   <groupId>org.testng</groupId>
   <artifactId>testng</artifactId>
   <version>7.1.0</version>
   <scope>test</scope>
  </dependency>
  <dependency>
   <groupId>org.seleniumhq.selenium</groupId>
   <artifactId>selenium-java</artifactId>
   <version>3.141.59</version>
  </dependency>
 </dependencies>
</project>

Steps to be followed to create Base Class
  • Declare web driver as static and Initialize the web driver and open the application using setup method.
  • Create an object of page layer class(Only need to create LoginPage object inside setup method).
  • Close the browser using tearDown method.
  • You can have some other common methods as well which will be used across framework like implicit waits, taking screen shots etc.
BaseClass.java
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import com.OrangeHRM.pages.LoginPage;

/**
 * @author Hitendra
 *  
 */
public class BaseClass {
 
 public static WebDriver driver;
 public LoginPage loginPage;
 
 @BeforeMethod
 public void setup() {
  System.setProperty("webdriver.chrome.driver",
    "C:\\Users\\Hitendra\\Downloads\\chromedriver_win32 (1)\\chromedriver.exe");
  driver= new ChromeDriver();
  driver.manage().window().maximize();
  driver.get("https://opensource-demo.orangehrmlive.com/index.php/auth/validateCredentials");
  loginPage=new LoginPage();
 }
 @AfterMethod
 public void tearDown() {
  driver.close();
 }
}

Steps to be followed to create page classes
  • Create a Java class for every page in the application (This class will extend BaseClass).
  • In each class, declare all the web Elements as variable using @FindBy.
  • Implement corresponding methods acting on the variables.
  • Construct page chaining logic - lets say in LoginPage.java we have login method and when we perform actions like entering username, password and clicking on login button then user lands HomePage. So login method will return object of HomePage.java class.
  • Add constructor to initialize the web elements initElements method.
Page Chaining Model
LoginPage.java
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;

import com.OrangeHRM.base.BaseClass;

public class LoginPage extends BaseClass {
 
 @FindBy(id="txtUsername") 
 WebElement userName;
 
 @FindBy(name="txtPassword") 
 WebElement password;
 
 @FindBy(xpath="//*[@id=\"btnLogin\"]") 
 WebElement loginBtn;
 
 @FindBy(xpath="//*[@id=\"divLogo\"]/img") 
 WebElement logo;
 
 public LoginPage() {
  PageFactory.initElements(driver, this);
 }
 
 public boolean validateLogo() {
  logo.isDisplayed();
  return true;
 }
 //This method will return object of HomePage class as we are landing on 
 //HomePage using this method
 public HomePage login(String uname, String pswd) {
  userName.sendKeys(uname);
  password.sendKeys(pswd);
  loginBtn.click();
  return new HomePage();
 }
}

HomePage.java
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
import com.OrangeHRM.base.BaseClass;

public class HomePage extends BaseClass {
 
 @FindBy(xpath="//*[@id=\"menu_admin_viewAdminModule\"]/b")
 WebElement adminTab;
 
 public HomePage() {
  PageFactory.initElements(driver, this);
 }
 //This method will return object of SystemUsersPage class as we are landing on 
 //SystemUsersPage using this method
 public SystemUsersPage clickOnAdminTab() {
  adminTab.click();
  return new SystemUsersPage();
 }
}

SystemUsersPage.java -  Just created this page class without writing anything inside it.
public class SystemUsersPage {

}

Steps to be followed to create test cases
  • Create test class for every corresponding page class. Like LoginPageTest, HomePageTest etc. (This class will extend BaseClass).
  • Using the object reference, call the method from page layer class.
  • Insert the assert in the test method to validate the scenarios.
  • Repeat step#3 until all actions are performed.
LoginPageTest.java
import org.testng.Assert;
import org.testng.annotations.Test;
import com.OrangeHRM.base.BaseClass;
import com.OrangeHRM.pages.HomePage;

public class LoginPageTest extends BaseClass {
 HomePage homePage;
 
 @Test(priority = 1)
 public void logoTest() {
  boolean flag=loginPage.validateLogo();
  Assert.assertTrue(flag);
 }
 @Test(priority = 2)
 public void loginTest() {
  homePage=loginPage.login("admin", "admin123");
  String expectedURL="https://opensource-demo.orangehrmlive.com/index.php/dashboard";
  String actualURL=BaseClass.driver.getCurrentUrl();
  Assert.assertEquals(actualURL, expectedURL);
 }
}

HomePageTest.java
import org.testng.Assert;
import org.testng.annotations.Test;
import com.OrangeHRM.base.BaseClass;
import com.OrangeHRM.pages.HomePage;

public class HomePageTest extends BaseClass {
 HomePage homePage;
 
 @Test(priority = 3)
 public void clickOnAdminTab() throws InterruptedException  {
  homePage=loginPage.login("admin", "admin123");
  homePage.clickOnAdminTab();
  Thread.sleep(2000);
  String expectedURL="https://opensource-demo.orangehrmlive.com/index.php/admin/viewSystemUsers";
  String actualURL=BaseClass.driver.getCurrentUrl();
  Assert.assertEquals(actualURL, expectedURL);
 }
}

testng.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite">
  <test thread-count="5" name="Test">
    <classes>
      <class name="com.OrangeHRM.testcases.LoginPageTest"/>
      <class name="com.OrangeHRM.testcases.HomePageTest"/>
    </classes>
  </test> <!-- Test -->
</suite> <!-- Suite -->

YouTube video will be coming soon...

Introduction to Page Object Model(POM)

What is Page Object Model?
Page Object Model is a design pattern to create Object Repository for web UI elements. Under this model, for each web page in the application, there should be corresponding page class. This Page class will find the Web Elements of that web page and also contains Page methods which perform operations on those Web Elements.
Non POM structure Vs POM Structure

POM Advantages and Disadvantages:
Advantages:
  • Object Repository: You can create an Object Repository of the fields segmented page-wise. This as a result provides a Page Repository of the application as well. Each page will be defined as a java class. All the fields in the page will be defined in an interface as members. The class will then implement the interface.
  • Reusability:  We can reuse the page class if required in different test cases .
  • Functional Encapsulation: All possible functionality or operations that can be performed on a page can be defined and contained within the same class created for each page. This allows for clear definition and scope of each page's functionality.
  • Low maintenance: Any User Interface changes can swiftly be implemented into the interface as well as class.
  • Programmer Friendly: Robust and more readable. The Object-oriented approach makes the framework programmer friendly.
  • Low Redundancy: Helps reduce duplication of code. If the architecture is correctly and sufficiently defined, the POM gets more done in less code.
  • Efficient & Scalable: Faster than other keyword-driven/data-driven approaches where Excel sheets are to be read/written.
Disadvantages:
  • High Setup Time & Effort:  Initial effort investment in development of Automation Framework is high. This is the biggest weight of POM in case of web applications with hundreds/thousands of pages. It is highly suggested that if this model is decided to be implemented, then it should be done parallel to development of the application.
  • Skilled labour: Testers not technically sound or aware of programming best practices are a nightmare in this case. 
There are two ways to implement Page Object Model.
Basic Approach 
Page Factory approach (@FindBy Annotation)

Steps to be followed to create page classes
  • Create a Java class for every page in the application.
  • In each class, declare all the web Elements as variable.
  • Implement corresponding methods acting on the variables.
Steps to be followed to create test cases
  • Initialize the driver and open the application.
  • Create an object of page layer class and pass the driver instance.
  • Using the object call the method from page layer class
  • Repeat step#3 until all actions are performed and at the end close the browser.
Below implementation given using basic approach:

LoginPage Class:
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;

public class LoginPage {
 WebDriver driver;
    //UI Elements
 By username = By.id("txtUsername");
 By password = By.name("txtPassword");
 By loginBtn = By.xpath("//*[@id=\"btnLogin\"]");
 By logo = By.xpath("//*[@id=\"divLogo\"]/img");
    
 //Constructor to initialize current class objects 
 public LoginPage(WebDriver driver) {
  this.driver=driver;
 }
 //User Actions methods
 public boolean validateLogo() {
  driver.findElement(logo).isDisplayed();
  return true;
 }
 public HomePage login(String uname, String pswd) {
  driver.findElement(username).sendKeys(uname);
  driver.findElement(password).sendKeys(pswd);
  driver.findElement(loginBtn).click();
  return new HomePage();
 }
}

LoginPageTest Class:
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.orangeHRM.pages.HomePage;
import com.orangeHRM.pages.LoginPage;

/**
 * @author Hitendra
 *  
 */
public class LoginPageTest {
 public WebDriver driver;
 LoginPage loginPage;
 HomePage homepage;
 
 @BeforeMethod
 public void setUp() {
  System.setProperty("webdriver.chrome.driver",
    "C:\\Users\\Hitendra\\Downloads\\chromedriver_win32 (1)\\chromedriver.exe");
  
  driver= new ChromeDriver();
  loginPage= new LoginPage(driver);
  driver.manage().window().maximize();
  driver.get("https://opensource-demo.orangehrmlive.com/index.php/auth/validateCredentials");
 }
 @Test
 public void varifyLogo() {
  
  boolean flag=loginPage.validateLogo();
  Assert.assertTrue(flag);
 }
 @Test
 public void varifyLogin() {
  homepage=loginPage.login("admin", "admin123");
  String actualURL= driver.getCurrentUrl();
  String expectedURL= "https://opensource-demo.orangehrmlive.com/index.php/dashboard";
  Assert.assertEquals(actualURL, expectedURL);
 }
 @AfterMethod
 public void tearDown() {
  driver.close();
 }
}

Please refer below YouTube video: