Quantcast
Channel: Pochampalli IT Labs
Viewing all articles
Browse latest Browse all 261

Integration of Cucumber 7 with TestNG 7 and Selenium 4 - Validate Login page with one session and Validate all the remaining scenarios with another single session

$
0
0
Hi

In this tutorial, we'll learn about how to integrate Cucumber with TestNG and Selenium. 

Test Strategy: 
Verify the OrangeHRM login page with valid credentials 
Verify the count of elements in Quick Launch panel in the Dashboard Tab/Page.
Verify the navigation to Directory Tab/Page from Dashboard Tab/Page 
Verify the existence of  Search button in the Directory Tab/Page


No Voice Video Tutorial (Walkthrough 

Click Me To Download ZIP archived Project

OR 

Clone the project from Github

Integration Approach: 
In this frame work, if we want to validate login page as well as other scenarios
we create one driver session for login validation and another driver session for remaining scenarios. 

That is, browser opens for twice - once for login validation  and second time for remaining scenarios validation. 
Execution of scenarios are independent of each other. 

We use BeforeAll hook of Cucumber framework to login into the application so all the scenarios except login scenario shares this driver session from it.

As we are including the validation of logging we quit the session of driver from BeforeAll since we are already logged into the app before all the scenarios run so login validation is not possible.

In the login step definitions we quit the session of the driver from hook and 
 initiate new driver session so login validation will be done 

After login validation is done driver is not quit so this session will be used by any other scenarios that runs randomly and after executing all the scenarios the driver quit from AfterAll hook. 


DISCLAIMER :
This is an experiment on how to avoid login for each scenario from various feature files as we normally use Background band in feature files for login purposes.
Adoption of this approach is one's own interest. 


Framework set-up consists of : 
1. Java 16 (Eclipse Build Path)
2. Cucumber Java 7.4.0 (pom.xml)
3. Cucumber TestNG 7.4.0 (pom.xml)
4. Selenium 4.3.0 (pom.xml)
5. Maven 3.8.1 (Embedded in Eclipse/Installed from Market Place)
   (To run the tests from command line install Apache Maven in Windows 10/11 - I've installed 3.8.6)

Steps to create the frame work: 
1. Download and install Cucumber plug-in in Eclipse from Market Place
2. Download and install TestNG plug-in in Eclipse from Market Place
3. Create a new Maven project (say : CucumberSeleniumTestNG)
4. Add cucumber-java, cucumber-testng and selenium dependencies in the pom.xml
5. Add Maven compiler dependency in pom.xml 
6. Create feature files(Gherkhin script) in src/main/resources folder
7. Create BasePage class for driver initialization and 
     create Hooks class for cucumber
     @BeforeAll and 
     @AfterAll
      that runs before all scenarios or after all the scenarios
      (Note that these are NOT TestNG annotations)
8. Write Step Definition Or Glue Code for the feature files
9. Create TestNG Cucumber Runner class, CucumberRunner.java
11. Create testng.xml for the project
12. Run Tests from TestNG Tests
13. Run Tests from testng.xml
14. Run Tests from Command line
15. Test results analysis from Cucumber report
16. Test results analysis from TestNG report

Project structure: 


1. Download and install Cucumber plug-in in Eclipse from Market Place
2. Download and install TestNG plug-in in Eclipse from Market Place
3. Create a new Maven project (say : CucumberSeleniumTestNG)
4. Add cucumber-java, cucumber-testng and selenium dependencies in the pom.xml
5. Add Maven compiler dependency in pom.xml 
pom.xml
Add the cucumber, testng and selenium dependencies and maven compiler as starting point. 
<projectxmlns="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>CucumberSeleniumTestNG</groupId>
<artifactId>CucumberSeleniumTestNG</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-java -->
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java</artifactId>
<version>7.4.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.4.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>

</dependencies>
<build>
<pluginManagement>
<plugins>
<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>

6. Create feature files(Gherkhin script) in src/main/resources folder

HRMLogin.feature
Gherikn script for login validation 
@HRMLogin
Feature: Login to HRM Application
I want to use this template for HRM Login page

@LoginValidCredentials
Scenario: LoginValidCredentials
Given User is on login page
When User enters username as "Admin" and password as "admin123"
Then User should be able to login successfully

Dashboard.feature
There are two sceanrios in this feature file
@Dasbhoard
Feature: Dashboard page
I want to use this template for my Dashboard Page

@DashboardTabCountOfQuickLaunhElements
Scenario: DashboardTabCountOfQuickLaunhElements
Then User finds the list of quick launch elements

  @DirectoryTabNavigationFromDashbaordTab
Scenario: DirectoryTabNavigationFromDashboardTab Then User clicks on Directory tab and verifies the navigation

Directory.feature
There is a scenario with Background added to the feature
@Directory
Feature: Dashboard page
I want to use this template for my Directory Page

Background:
Then User is on Directory page

@DirectoryTabIsSearchButtonDisplayed
Scenario: DirectoryTabIsSearchButtonDisplayed
Then Is Search button displayed

7. Create BasePage class for driver initialization and 
     create Hooks class for cucumber
     @BeforeAll and 
     @AfterAll
      that runs before all scenarios or after all the scenarios
      (Note that these are NOT TestNG annotations)

BasePage.java
In the BasePage we initiate the driver; if we want to do command line execution of scenarios from a generated jar, main() method has to be included and this class best suites for it. 
package com.sadakar.common;
importorg.openqa.selenium.WebDriver;
publicclassBasePage{

publicstatic WebDriver driver;

}

Hooks.java
In the BeforeAll (This is a cucumber annotation/hook) hook we are logging into the application and use this driver session for all the scenarios so multiple log-in for each scenario is avoidable except for login validation. 

quit the driver after executing all the scenarios is done using AfterAll hook (This is a cucumber annotation/hook)
package com.sadakar.common;

importjava.time.Duration;

importorg.openqa.selenium.By;
importorg.openqa.selenium.chrome.ChromeDriver;

importio.cucumber.java.AfterAll;
importio.cucumber.java.BeforeAll;

publicclassHooksextends BasePage {

@BeforeAll
publicstaticvoidsetupDriver()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");
driver.findElement(By.xpath("//*[@id=\"txtUsername\"]")).sendKeys("Admin");
driver.findElement(By.xpath("//*[@id=\"txtPassword\"]")).sendKeys("admin123");
driver.findElement(By.id("btnLogin")).submit();
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5));
}

@AfterAll
publicstaticvoidquitDriver()throws Exception {
driver.quit();
}

}

8. Write Step Definition Or Glue Code for the feature files
HRMLoginPage.java

We are already in logged in into the application in BeforeAll hook - so how to validate login ? 
When the driver begins executing this scenario, we quit the driver (driver.quit()) first and then a initiatate  a new driver and then logging back to the application that means the new driver is alive. 

As the cucumber scenarios executes randomly, if there are any other scenarios to be executed those scenarios will use the secondly generated driver from the login done page. 

package com.sadakar.stepdefinitions;

importjava.time.Duration;
importorg.openqa.selenium.By;
importorg.openqa.selenium.chrome.ChromeDriver;

importcom.sadakar.common.BasePage;
importio.cucumber.java.en.Given;
importio.cucumber.java.en.Then;
importio.cucumber.java.en.When;

publicclassHRMLoginPageextends BasePage {

@Given("User is on login page")
publicstaticvoidhomePage()throws InterruptedException {

driver.quit();

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");

}

@When("User enters username as {string} and password as {string}")
publicvoidenterUserNamePassword(String userName, String password){

driver.findElement(By.xpath("//*[@id=\"txtUsername\"]")).sendKeys(userName);
driver.findElement(By.xpath("//*[@id=\"txtPassword\"]")).sendKeys(password);
}

@Then("User should be able to login successfully")
publicvoidclickSubmitLogin(){
driver.findElement(By.id("btnLogin")).submit();
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5));
}

}

DashboardPage.java
There are two scenarios in Dashboard.feature file , one scenario is to count the elements and other scenario is to navigate from Dashboard to Dictionary. 
In this class, we have the step definition code for those two scenarios. 
package com.sadakar.stepdefinitions;

importjava.time.Duration;
importjava.util.ArrayList;
importjava.util.List;
importorg.openqa.selenium.By;
importorg.openqa.selenium.WebElement;
importorg.testng.Assert;

importcom.sadakar.common.BasePage;

importio.cucumber.java.en.Then;

publicclassDashboardPageextends BasePage {

@Then("User finds the list of quick launch elements")
publicvoidlistOfQuickLaunchElementsOnDashboardPage(){

// Adding table data of a row to WebElement List
List<WebElement> actualListOfQuickLaunchElements = driver
.findElements(By.xpath("//*[@id=\"dashboard-quick-launch-panel-menu_holder\"]/table/tbody/tr/td"));

// Display the table data of row from the WebElementList
for(WebElement ele : actualListOfQuickLaunchElements){
System.out.println(ele.getText());
}

// Display the size of WebElement List
System.out.println("Size of Quick launch elements : "+ actualListOfQuickLaunchElements.size());

// Adding WebElements List to a ArrayList
List<String> quickLaunchElementsArrayList =new ArrayList<String>();
for(WebElement ele : actualListOfQuickLaunchElements){
quickLaunchElementsArrayList.add(ele.getText());
}
// Displaying the WebElements from the ArrayList
for(WebElement s : actualListOfQuickLaunchElements){
System.out.println(s.getText());
}
// Size of the ArrayList
System.out.println("Size of Array list : "+ quickLaunchElementsArrayList.size());

// Preparing expected list of elements

@SuppressWarnings("serial")
List<String> expecteListOfQuickLaunchElements =new ArrayList<String>(){
{
add("Assign Leave");
add("Leave List");
add("Timesheets");
add("Apply Leave");
add("My Leave");
add("My Timesheet");
}
};

// comparing actual list with expected list
for(int i =0; i < actualListOfQuickLaunchElements.size(); i++){
String actualLabels = actualListOfQuickLaunchElements.get(i).getText();
String expectedLabels = expecteListOfQuickLaunchElements.get(i);
Assert.assertEquals(actualLabels, expectedLabels);
}
}

@Then("User clicks on Directory tab and verifies the navigation")
publicvoidnavigateToDirectoryTabFromDashbaordTab(){

driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(20));
driver.findElement(By.xpath("//*[@id=\"menu_directory_viewDirectory\"]")).click();
}
}

DirectoryPage.java
In the Directory feature we are validation whether the Search button is displayed or not. 
package com.sadakar.stepdefinitions;

importorg.openqa.selenium.By;

importcom.sadakar.common.BasePage;

importio.cucumber.java.en.Then;

publicclassDirectoryPageextends BasePage{

@Then("User is on Directory page")
publicvoiduser_is_on_directory_page(){
driver.findElement(By.xpath("//*[@id=\"menu_directory_viewDirectory\"]/b")).click();
}

@Then("Is Search button displayed")
publicvoidisSearchButtonDisplayed(){

driver.findElement(By.xpath("//*[@id=\"searchBtn\"]")).isDisplayed();
}
}

9. Create TestNG Cucumber Runner class, CucumberRunner.java
CucumberRunner.java
In the cucumber 7 the tags takes new format 
For example: 
Single tag : 
tags="@LoginValidCredentials",

Two tags :
tags="@LoginValidCredentials or @DashboardTabCountOfQuickLaunhElements",

Negate a tag : 
tags="@LoginValidCredentials and not @DashboardTabCountOfQuickLaunhElements", 

CucumberRunner class extends the AbstractTestNGCucumberTests

package com.sadakar.testng.runner;

importio.cucumber.testng.AbstractTestNGCucumberTests;
importio.cucumber.testng.CucumberOptions;

@CucumberOptions(


//tags="@LoginValidCredentials",
//tags="@DashboardTabCountOfQuickLaunhElements",
//tags="@DirectoryTabNavigationFromDashboardTab",
//tags="@DirectoryTabIsSearchButtonDisplayed",
tags="@LoginValidCredentials or @DashboardTabCountOfQuickLaunhElements or @DirectoryTabNavigationFromDashboardTab or @DirectoryTabIsSearchButtonDisplayed",

//tags="@LoginValidCredentials and not @DashboardTabCountOfQuickLaunhElements and not @DirectoryTabNavigationFromDashboardTab or @DirectoryTabIsSearchButtonDisplayed",

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

plugin ={"pretty","json:target/cucumber-reports/cucumber.json","html:target/cucumber-reports/cucumberreport.html"},

monochrome =true)
publicclassCucumberRunnerextends AbstractTestNGCucumberTests {


}

11. Create testng.xml for the project
testng.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suitename="Suite">
<testthread-count="5"name="Test">
<classes>
<classname="com.sadakar.testng.runner.CucumberRunner"/>
</classes>
</test><!-- Test -->
</suite><!-- Suite -->

12. Run Tests from TestNG Tests



13. Run Tests from testng.xml
14. Run Tests from Command line
    <TBD>
15. Test results analysis from Cucumber report


16. Test results analysis from TestNG report

Click on the images to Zoom In




Emailable-report.html:

index.html


I hope you find it useful ! Stay tuned for more learnings. 

Viewing all articles
Browse latest Browse all 261

Trending Articles