DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Day in the Life of a Developer With Google’s Gemini Code Assist: Part 1
  • That Can Not Be Tested!: Spring Cache and Retry
  • Supercharging Productivity in Microservice Development With AI Tools
  • Improving Customer-Facing App Quality Using Tricentis Testim

Trending

  • Revolutionizing Financial Monitoring: Building a Team Dashboard With OpenObserve
  • Transforming AI-Driven Data Analytics with DeepSeek: A New Era of Intelligent Insights
  • Unmasking Entity-Based Data Masking: Best Practices 2025
  • AI-Based Threat Detection in Cloud Security
  1. DZone
  2. Data Engineering
  3. Databases
  4. Creating Extent Reports in Selenium Using the Extent API

Creating Extent Reports in Selenium Using the Extent API

Learn how to implement the Extent API in Selenium using TestNG to create more interactive reports, a dashboard view, emailable reports, and more.

By 
Aswani Kumar Avilala user avatar
Aswani Kumar Avilala
DZone Core CORE ·
Feb. 27, 18 · Tutorial
Likes (7)
Comment
Save
Tweet
Share
58.3K Views

Join the DZone community and get the full member experience.

Join For Free

The Extent API can produce more interactive reports, a dashboard view, graphical view, capture screenshots as images in the reports, and emailable reports which can be mailed right after the unit test is completed.

The Extent API can be configured to support programming languages like Java and .Net and unit testing frameworks like JUnit, TestNG, NUnit, etc.

Implementation of Extent API in Selenium Using TestNG 

To create reports with the Extent API, we need to follow the below steps.

Create a Maven project in Eclipse and add artifacts like Selenium, TestNG, and the Extent API as dependencies in the pom.xml, as shown below:

<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>com.selenium</groupId>
<artifactId>PageObjectModel</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.8.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.relevantcodes/extentreports -->
<dependency>
<groupId>com.relevantcodes</groupId>
<artifactId>extentreports</artifactId>
<version>2.41.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.testng/testng -->
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.11</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
</dependencies>
</project>

Create a listener class using ITestListener to capture the log messages in the Extent Reports when a test event occurs, as shown below. The Extent API uses the ExtentReports and ExtentTest class to generate reports

  • The ExtentReports object is used to generate an HTML report in the specified location. The path of the report is given as an argument in the ExtentReports constructor.

  • ExtentTest is initialized from the ExtentReports object by calling the lifecycle methods of reports. To start the log information in the reports, call startTest(). The return of startTest() is assigned to the test as a reference variable to ExtentTest.

  • The LogStatus enum is used to add the status message based on the test execution. We have constant values in LogStatus like INFO, PASS, FAIL, SKIP, ERROR, FATAL, WARNING, and UNKNOWN. Call the status message in the respective lifecycle method to get the appropriate message in the report.

  • End the test reports by calling endTest() and flush() from the reports to properly close the resources.

/**
 * @author aswani.kumar.avilala
 */
package com.listeners;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.ITestContext;
import org.testng.ITestListener;
import org.testng.ITestResult;
import com.relevantcodes.extentreports.ExtentReports;
import com.relevantcodes.extentreports.ExtentTest;
import com.relevantcodes.extentreports.LogStatus;

public class MyListener implements ITestListener {

 protected static WebDriver driver;
 protected static ExtentReports reports;
 protected static ExtentTest test;

 public void onTestStart(ITestResult result) {
  System.out.println("on test start");
  test = reports.startTest(result.getMethod().getMethodName());
  test.log(LogStatus.INFO, result.getMethod().getMethodName() + "test is started");
 }
 public void onTestSuccess(ITestResult result) {
  System.out.println("on test success");
  test.log(LogStatus.PASS, result.getMethod().getMethodName() + "test is passed");
 }
 public void onTestFailure(ITestResult result) {
  System.out.println("on test failure");
  test.log(LogStatus.FAIL, result.getMethod().getMethodName() + "test is failed");
  TakesScreenshot ts = (TakesScreenshot) driver;
  File src = ts.getScreenshotAs(OutputType.FILE);
  try {
   FileUtils.copyFile(src, new File("C:\\images\\" + result.getMethod().getMethodName() + ".png"));
   String file = test.addScreenCapture("C:\\images\\" + result.getMethod().getMethodName() + ".png");
   test.log(LogStatus.FAIL, result.getMethod().getMethodName() + "test is failed", file);
   test.log(LogStatus.FAIL, result.getMethod().getMethodName() + "test is failed", result.getThrowable().getMessage());
  } catch (IOException e) {
   e.printStackTrace();
  }
 }
 public void onTestSkipped(ITestResult result) {
  System.out.println("on test skipped");
  test.log(LogStatus.SKIP, result.getMethod().getMethodName() + "test is skipped");
 }
 public void onTestFailedButWithinSuccessPercentage(ITestResult result) {
  System.out.println("on test sucess within percentage");
 }
 public void onStart(ITestContext context) {
  System.out.println("on start");
  driver = new ChromeDriver(); // Set the drivers path in environment variables to avoid code(System.setProperty())
  reports = new ExtentReports(new SimpleDateFormat("yyyy-MM-dd hh-mm-ss-ms").format(new Date()) + "reports.html");
 }
 public void onFinish(ITestContext context) {
  System.out.println("on finish");
  driver.close();
  reports.endTest(test);
  reports.flush();
 }

}


Design a Register Page using the Page Object Model design pattern, as shown below:    

/**
 * @author aswani.kumar.avilala
 */
package com.pages;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;

public class MercuryToursRegisterPage {

 WebDriver driver;
 @FindBy(xpath = "//input[@name='email']") WebElement email;
 @FindBy(xpath = "//input[@name='password']") WebElement password;
 @FindBy(css = "input[name='confirmPassword']") WebElement confirmPassword;
 @FindBy(name = "register") WebElement register;
 @FindBy(linkText = "SIGN-OFF") WebElement signoff;

 public MercuryToursRegisterPage(WebDriver driver) {
  super();
  this.driver = driver;
 }
 public String clickUserInfo() {
  email.sendKeys("askmail29");
  password.sendKeys("askmail29");
  confirmPassword.sendKeys("askmail29");
  register.click();
  return driver.getTitle();
 }
 public void clickSignOff() {
  signoff.click();
 }


}

    

Design a Login Page using the Page Object Model as a design pattern, as shown below:

/**
 * @author aswani.kumar.avilala
 */
package com.pages;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.How;

public class MercuryToursLoginPage {

 WebDriver driver;
 @FindBy(name = "userName") WebElement username;
 @FindBy(how = How.NAME, using = "password") WebElement password;
 @FindBy(how = How.XPATH, using = "//input[@value='Login']") WebElement signin;
 @FindBy(linkText = "REGISTER") WebElement register;

 public MercuryToursLoginPage(WebDriver driver) {
  super();
  this.driver = driver;
 }
 public String clickLogin() {
  username.sendKeys("askmail29");
  password.sendKeys("askmail29");
  signin.click();
  return driver.getTitle();
 }
 public void clickRegister() {
  register.click();
 }
 public void loadWebPage(String url) {
  driver.get(url);
  driver.manage().window().maximize();
  driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
 }
}


Design a test class which contains the actual call to the object repository created in the Page       classes:

/**
 * @author aswani.kumar.avilala
 */
package com.tests;
import org.testng.annotations.Test;
import com.listeners.MyListener;
import com.pages.MercuryToursLoginPage;
import com.pages.MercuryToursRegisterPage;
import com.relevantcodes.extentreports.LogStatus;
import org.testng.annotations.BeforeTest;
import org.openqa.selenium.support.PageFactory;
import org.testng.Assert;
import org.testng.annotations.AfterTest;

public class TestApp extends MyListener {

 MercuryToursLoginPage mlp;
 MercuryToursRegisterPage mrp;

 @BeforeTest
 public void beforeTest(String browserName) {
  mlp = PageFactory.initElements(driver, MercuryToursLoginPage.class);
  mrp = PageFactory.initElements(driver, MercuryToursRegisterPage.class);
 }
 @AfterTest
 public void afterTest() {
  System.out.println("in after test");
  mlp = null;
  mrp = null;
 }
 @Test
 public void testMercuryTours() {
  System.out.println("in test method");
  mlp.loadWebPage("http://newtours.demoaut.com");
  mlp.clickRegister();
  mrp.clickUserInfo();
  mrp.clickSignOff();
  String title = mlp.clickLogin();
  Assert.assertEquals(title, "Find a Flight: Mercury Tours:");
  test.log(LogStatus.INFO, "the test tours is passed");
 }

}


Configure the testng.xml file with listeners and the test classes. Attach the listener class to the test in the testng.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite" parallel="tests">
<listeners>
<listener class-name="com.listeners.MyListener"></listener>
</listeners>
<test name="Test1">
<classes>
<class name="com.tests.TestApp" />
</classes>
</test>
</suite>
<!-- Suite -->


Execute the test as a suite, as shown below:

Image title

Reports are generated in the project structure with the file name as the SimpleDateFormat.html files.

When there is a failure in the test, the onTestFailure() lifecycle method is called from the listener class as it captures the screen and adds the captured image to the report, as shown below:Image title

When all the tests are passed, the report is shown, the onTestSuccess() lifecycle method is called from the listener class, and the respective report is generated, as shown below:

Image title

We can also view the reports in the form of a dashboard, as shown below:   

Image title

API Extent (file systems) unit test

Opinions expressed by DZone contributors are their own.

Related

  • Day in the Life of a Developer With Google’s Gemini Code Assist: Part 1
  • That Can Not Be Tested!: Spring Cache and Retry
  • Supercharging Productivity in Microservice Development With AI Tools
  • Improving Customer-Facing App Quality Using Tricentis Testim

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!