Monday, 18 July 2022

Page Object Model (POM) in selenium with cucumber testng, maven | end to end example

POM - Page Object Model 

  • It is a design pattern / frame work in selenium. 
  • Using this pattern, we can create object repository for web elements in the UI.
  • We create a POM class file(Example: HRMLoginPOM.java) for each web page such that it consists of all web elements present in the page. 
  • Testing scripts(Example: HRMLogin.java) uses the the elements from POM class file 

Project Structure: 



Source Code :  Download from GitHub or Click this link

Or Watch this No Voice Video Tutotial for the same example 



Steps: 

  • Download and install cucumber plug-in in Eclipse from Market Place

  • Download and install TestNG plug-in in Eclipse from Market Place

  • Create a new Maven project (say : CucucumberTestNGSeleniumMavenPageObjectModel)

  • Add the following dependencies in  pom.xml
    • cucumber-java 7.1.0
    • cucumber-testng 7.1.0
    • selenium-java 4.3.0
    • testng 7.1.0
  • Add the following plug-ins in pom.xml 
    •  maven-surefire-plugin 3.0.0-M7
    •  maven-compiler-plugin 3.10.1
  • Create feature files in 
    • folder: src/test/resources
    • HRMLogin.feature
    • Directory.feature
  • Write code for cucumber runner
    • folder : src/test/java
    • package : com.sadakar.testng.runner
    • class : RunCucumberTest.java

  • Write code for driver, hooks 
    • folder : src/test/java
    • package: com.sadakar.common
    • BasePage.java for driver 
    • Hooks.java for Before and After cucumber hooks

  • Write code for page objects 
In this phase, implement page objects in separate classes for each of the UI page and refer them wherever required in steps definitions. In a long term, if there are any changes in locators, we can just refer to the particular POM class and update at once. 
Using this approach we can also reduce the code redundancy.  
    • folder : src/test/java
    • package: com.sadakar.pageobjects
    • HRMLoginPOM.java for HRMLogin page web elements, 
      • for instance locating username, password and login button 
    • DirectoryPOM.java for Directory page web element, 
      • for instance view directory tab link, search button 
  • Write code for step definitions or say glue code 
    • HRMLogin.java 
    • Directory.java

  • Run the scenarios from mvn command line 
    • Navigate to the project folder 
    • Run the below command for two scenarios. 

      mvn test -Dcucumber.filter.tags="@LoginValidCredentials or @DirectoryTabIsSearchButtonDisplayed"

      Tap on the image for best view: 

  • Run the scenarios from TestNG in eclipse and report analysis
    • Right click on the project and then Run as TestNG
    • Report will be generated at 
      • test-output> emailable-report.html
    • Tap on the image for best view: 

  • Run the project using testng.xml 
    • Right click on the project > Run as testng.xml
    • Report is same as above
    • Make sure testng.xml is added in pom.xml file as configuration

  • Analysis of cucumber report
    • Cucumber report is available at
      • target > cucumber-reports > cucumberreport.html
    • Tap on the image for better view. 


Now, based on above steps, find the code below for features, POM classes, step definition classes, runner classes, Driver and Hooks classes. 

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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>CucucumberTestNGSeleniumMavenPageObjectModel</groupId>
	<artifactId>CucucumberTestNGSeleniumMavenPageObjectModel</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>
	<dependencies>
		<!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-java -->
		<dependency>
			<groupId>io.cucumber</groupId>
			<artifactId>cucumber-java</artifactId>
			<version>7.1.0</version>

		</dependency>
		<!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-java -->
		<!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-testng -->
		<dependency>
			<groupId>io.cucumber</groupId>
			<artifactId>cucumber-testng</artifactId>
			<version>7.1.0</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
		<dependency>
			<groupId>org.seleniumhq.selenium</groupId>
			<artifactId>selenium-java</artifactId>
			<version>4.3.0</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.testng/testng -->
		<dependency>
			<groupId>org.testng</groupId>
			<artifactId>testng</artifactId>
			<version>7.1.0</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-compiler-plugin -->

		<dependency>
			<groupId>tech.grasshopper</groupId>
			<artifactId>extentreports-cucumber7-adapter</artifactId>
			<version>1.7.0</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/com.aventstack/extentreports -->
		<dependency>
			<groupId>com.aventstack</groupId>
			<artifactId>extentreports</artifactId>
			<version>5.0.8</version>
		</dependency>
	</dependencies>
	<build>
		<pluginManagement>
			<plugins>
				<plugin>
					<groupId>org.apache.maven.plugins</groupId>
					<artifactId>maven-surefire-plugin</artifactId>
					<version>3.0.0-M7</version>
					<configuration>
						<suiteXmlFiles>
							<suiteXmlFile>testng.xml</suiteXmlFile>
						</suiteXmlFiles>
						<systemPropertyVariables>
							<extent.reporter.spark.start>true</extent.reporter.spark.start>
							<extent.reporter.spark.out>test-output/SparkReport/Spark.html</extent.reporter.spark.out>
						</systemPropertyVariables>
					</configuration>
				</plugin>
				<plugin>
					<groupId>org.apache.maven.plugins</groupId>
					<artifactId>maven-compiler-plugin</artifactId>
					<version>3.10.1</version>
					<configuration>
						<source>1.8</source>
						<target>1.8</target>
						<encoding>UTF-8</encoding>
					</configuration>
				</plugin>
			</plugins>
		</pluginManagement>
	</build>
</project>


HRMLogin.feature

@HRMLogin
Feature: Login to HRM Application
  I want to use this template for HRM Login page

  @LoginValidCredentials
  Scenario: LoginValidCredentials
    Given User login to HRM application with UserName and Password
      | Admin | admin123 |

Directory.feature
@Directory
Feature: Dashboard page
  I want to use this template for my Directory Page

  Background: 
    Given User login to HRM application with UserName and Password
      | Admin | admin123 |

  @DirectoryTabIsSearchButtonDisplayed
  Scenario: DirectoryTabIsSearchButtonDisplayed
    Then User is on Directory page
    Then Is Search button displayed

RunCucumberTest.java
package com.sadakar.testng.runner;

import io.cucumber.testng.AbstractTestNGCucumberTests;
import io.cucumber.testng.CucumberOptions;

@CucumberOptions(

		tags = "@LoginValidCredentials or @DirectoryTabIsSearchButtonDisplayed",

		features = "classpath:features", glue = { "com.sadakar.common", "com.sadakar.stepdefinitions",
				"com.sadakar.testng.runner" },

		plugin = { "pretty", "json:target/cucumber-reports/cucumber.json",
				"html:target/cucumber-reports/cucumberreport.html", 
				"com.aventstack.extentreports.cucumber.adapter.ExtentCucumberAdapter:"},

		monochrome = true)
public class RunCucumberTest extends AbstractTestNGCucumberTests {

}

BasePage.java
package com.sadakar.common;
import org.openqa.selenium.WebDriver;
public class BasePage {
	
	public static WebDriver driver;

}

Hooks.java
package com.sadakar.common;
import org.openqa.selenium.chrome.ChromeDriver;
import io.cucumber.java.After;
import io.cucumber.java.Before;

public class Hooks extends BasePage {

	@Before //Cucumber Before Hook
	public static void setupDriver() throws InterruptedException {

		System.setProperty("webdriver.chrome.driver", "D:\\chromedriver.exe");
		driver = new ChromeDriver();
		driver.manage().window().maximize();
		driver.get("https://opensource-demo.orangehrmlive.com/index.php/auth/login");
	}

	@After // Cucumber After hook
	public static void quitDriver() throws Exception {
		driver.quit();
	}

}

HRMLoginPOM.java
package com.sadakar.pageobjects;

import org.openqa.selenium.By;

public class HRMLoginPOM {

	// Locators for username, password, loginButton
	public By userNameLocator = By.xpath("//*[@id=\"txtUsername\"]");
	public By passwordLocator = By.xpath("//*[@id=\"txtPassword\"]");
	public By loginButtonLocator = By.id("btnLogin");

}

DirecotryPOM.java
package com.sadakar.pageobjects;

import org.openqa.selenium.By;

public class DirectoryPOM {

	// locators for view Directory Page/Tab, Search button
	public By viewDirectoryLinkLocator = By.xpath("//*[@id=\"menu_directory_viewDirectory\"]");
	public By searchButtonLocator = By.xpath("//*[@id=\"searchBtn\"]");

}

HRMLogIn.java
package com.sadakar.stepdefinitions;

import java.time.Duration;
import java.util.List;
import com.sadakar.common.BasePage;
import com.sadakar.pageobjects.HRMLoginPOM;

import io.cucumber.java.en.Given;

public class HRMLogin extends BasePage {

	HRMLoginPOM hrm = new HRMLoginPOM();

	@Given("User login to HRM application with UserName and Password")
	public void loginToHRMApp(io.cucumber.datatable.DataTable dataTable) {

		List<List<String>> cells = dataTable.cells();

		driver.findElement(hrm.userNameLocator).sendKeys(cells.get(0).get(0));
		driver.findElement(hrm.passwordLocator).sendKeys(cells.get(0).get(1));
		driver.findElement(hrm.loginButtonLocator).submit();
		driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5));
	}
}

Directory.java
package com.sadakar.stepdefinitions;

import java.time.Duration;

import org.openqa.selenium.WebElement;
import org.testng.Assert;

import com.sadakar.common.BasePage;
import com.sadakar.pageobjects.DirectoryPOM;

import io.cucumber.java.en.Then; 
public class Directory extends BasePage{

	DirectoryPOM dir = new DirectoryPOM();
	
	@Then("User is on Directory page")
	public void directoryPage() {

		// Navigating to Directory Page/tab
		driver.findElement(dir.viewDirectoryLinkLocator).click();
		driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5));
	}
	
	@Then("Is Search button displayed")
	public void isSearchButtonDisplayed() {
	
		// Verifying Search button is displayed or not
		WebElement searchButtonEle = driver.findElement(dir.searchButtonLocator);
		Assert.assertTrue(searchButtonEle.isDisplayed());
	}
}

Cheers!, I hope this helped you implement Page Object Model using cucumber, selenium and testng. 
This article also has extent-reports included that is not discussed in steps. 

No comments:

Post a Comment