Extent Reports in Automation – TestNG

maxresdefault

     TestNG itself, providing an HTML report in test-output folder. I had a thought of building custom report for automation, after that I built one PDF customized report using iText PDF Java library and took more effort to build it. Later I thought to build a custom beautiful high rich HTML reports with minimum effort; that time Extent Report comes into my mind. Here, I would like to share the details on the integration and implementation of Extent Report utility in Automation test classes that built with TestNG.

Prerequisites to Generate Extent Reports:

  1. Java should be installed and setup Java
  2. TestNG maven dependency should be available
  3. Selenium maven dependency should be available
  4. Extent Report Maven dependency should be available
  5. extent-config.xml – It allows to configure HTML Report

Steps To Generate Extent Reports:

  1. Firstly, create a maven project.
  2. Add TestNG dependency to pom.xml of project in eclipse.
  3. Add selenium-java and selenium-server dependencies to pom.xml of  project in eclipse
  4. Extent Report Maven dependency (version: 2.41.2) should available and added in pom.xml project in eclipse.
  5. Create a java class say ‘SeleniumExtentReport’ and add following code to it,

package com.journeyofquality.test;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
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.Assert;
import org.testng.ITestResult;
import org.testng.SkipException;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.Test;
import com.relevantcodes.extentreports.ExtentReports;
import com.relevantcodes.extentreports.ExtentTest;
import com.relevantcodes.extentreports.LogStatus;

public class SeleniumExtentReport {
ExtentReports extentReport;
ExtentTest extentTest;
WebDriver driver;

@BeforeSuite
public void beforeSuite() {
//In before suite we are creating HTML report template, adding basic information to it and load the extent-config.xml file

extentReport = new ExtentReports(System.getProperty(“user.dir”) + “/test-output/SeleniumExtentReport.html”,
true);
extentReport.addSystemInfo(“Host Name”, “JourneyofQuality”).addSystemInfo(“Environment”, “Automation Testing”)
.addSystemInfo(“User Name”, “Sanoj”);
extentReport.loadConfig(new File(System.getProperty(“user.dir”) + “\\extent-config.xml”));
}

@BeforeClass
public void beforeClass() {
System.setProperty(“webdriver.chrome.driver”, );
driver = new ChromeDriver();
}

@BeforeMethod
public void beforeMethod(Method method) {
//In before method we are collecting the current running test case name
String className = this.getClass().getSimpleName();
extentTest = extentReport.startTest(className + “-” + method.getName());
}

@Test
public void passTest() {
Assert.assertTrue(true);
}

@Test
public void failTest() {
driver.get(“http://google.com”);
Assert.assertEquals(driver.getTitle().toString(), “Journey”);
}

@Test
public void skipTest() {
throw new SkipException(“Skipping – This is not ready for testing “);
}

@AfterMethod
public void getResult(ITestResult result, Method method) throws Exception {
//In after method we are collecting the test execution status and based on that the information writing to HTML report
if (result.getStatus() == ITestResult.FAILURE) {
extentTest.log(LogStatus.FAIL, “Test Case Failed is ” + result.getName());
String screenshotPath = SeleniumExtentReport.capture(driver, result.getName());
extentTest.log(LogStatus.FAIL, “Error Details :- \n” + result.getThrowable().getMessage()
+ extentTest.addScreenCapture(screenshotPath));
}
if (result.getStatus() == ITestResult.SKIP) {
extentTest.log(LogStatus.SKIP, “Test Case Skipped is ” + result.getName());
}
if (result.getStatus() == ITestResult.SUCCESS) {
extentTest.log(LogStatus.PASS, “Test Case Passed is ” + result.getName());
}
}

@AfterSuite
public void endReport() {
//In after suite stopping the object of ExtentReports and ExtentTest
extentReport.endTest(extentTest);
extentReport.flush();
driver.quit();
}

/**

* To Capture the Screenshot and return the file path to extent report fail
* cases
*
* @param driver
* @param screenShotName
* @return
* @throws IOException
*/
private static String capture(WebDriver driver, String screenShotName) throws IOException {
String dest = null;
try {
SimpleDateFormat dateFormat = new SimpleDateFormat(“dd-mm-yyyy h-m-s”);
Date date = new Date();
TakesScreenshot ts = (TakesScreenshot) driver;
File source = ts.getScreenshotAs(OutputType.FILE);
dest = System.getProperty(“user.dir”) + “\\ErrorScreenshots\\” + screenShotName + dateFormat.format(date)
+ “.png”;
File destination = new File(dest);
FileUtils.copyFile(source, destination);
} catch (Exception e) {
e.getMessage();
System.out.println(e.getMessage());
}
return dest;
}
}

Code Explanation:

  • Imported two classes ExtentReports and ExtentTest.
    • ExtentReportsBy using this class we set the path where our reports need to generate.
    • ExtentTestBy using this class we could generate the logs in the report.
  • Took three methods with @Test annotation such as passTest, failTest and skipTest and a method beforeSuite with @BeforeSuite annotation, beforeMethod with @BeforeMetod annotation, another method getResult with @AfterMethod annotation and finally, endReport with @AfterSuite annotation.
  • Here my intention is to generate a report with all the three types of results such as Pass, Fail and Skip.
  • Used object of ExtentReports class (i.e., extentReport) in the beforeSuite method which was assigned to @BeforeSuite annotation to generate the HTML report in the required path.
  • Used object of ExtentTest class (i.e., extentTest) in beforeMethod to get the name of currently executing test case. Also, extentTest object used in getResult method which was assigned to @AfterMethod annotation to write logs in the report.
  • Used ITestResult class in the @AfterMethod to describe the result of a test.

extent-config.xml: 

     By using this external XML file (extent-config.xml), we could change the details such as Report Theme (either standard or dark), Report Title, Document Title etc., We use extent object and use loadConfig() method to load this XML file.

<?xml version=”1.0″ encoding=”UTF-8″?>
<extentreports>
<configuration>
<!– report theme –>
<!– standard, dark –>
<theme>standard</theme>
<!– document encoding –>
<!– defaults to UTF-8 –>
<encoding>UTF-8</encoding>
<!– protocol for script and stylesheets –>
<!– defaults to https –>
<protocol>https</protocol>
<!– title of the document –>
<documentTitle>JourneyOfQuality</documentTitle>
<!– report name – displayed at top-nav –>
<reportName>JourneyOfQuality</reportName>
<!– report headline – displayed at top-nav, after reportHeadline –>
<reportHeadline>Automation Report</reportHeadline>
<!– global date format override –>
<!– defaults to yyyy-MM-dd –>
<dateFormat>yyyy-MM-dd</dateFormat>
<!– global time format override –>
<!– defaults to HH:mm:ss –>
<timeFormat>HH:mm:ss</timeFormat>
<!– default style override –>
<theme></theme>
<!– custom javascript –>
<scripts>
<![CDATA[
$(document).ready(function() {
$(“.logo-content”).hide();
$(“.logo-container”).html(“JourneyOfQuality”);
$(‘#parentNodes’).prop(“checked”, true).click();
$(‘#test-count-setting > div.modal-footer > a’)[0].click();
});
]]>
</scripts>
<!– custom styles –>
<styles>
<![CDATA[
]]>
</styles>
</configuration>
</extentreports>

     Refresh the project after execution of above SeleniumExtentReport.java file. You could find an HTML file named “SeleniumExtentReport.html” in your test-output folder. Copy the location of the “SeleniumExtentReport.html” file and open it by using any browser. You could see beautiful high rich HTML reports as shown below.

Capture

Capture1

Try to implement the above mentioned custom report mechanism in your Selenium – Java -TestNG and enjoy automation.

make it perfect !

Automation and BDD Framework using Cucumber

     In this article, I would like to share the concept of configuring BDD (behavior-driven development) and running of Selenium using Cucumber. Cucumber –JVM is based on cucumber framework which allows to writes feature file in plain text using Gherkin language, this feature is supported by step definitions file which has implemented automation code of Webdriver.

Configuration and Implementation

Seven Steps to configure BDD (behavior-driven development) and running of Selenium or Appium using Cucumber – JVM:

1. First create a maven eclipse project.

2. Create pom.xml and add all the dependendcies

3. Create a feature file and put into “resources” folder.

4. Create step definition file for above scenario and implement WebDriver (for Web based applications) or AppiumDriver (for native applications) automation code. So Create a java file to keep the step definition and put this file under respective package of source folder” src/main/java”.

5. Create Cucumber runner java class which defines cucumber-jvm configuration and put under respective package of source folder ” src/test/java”.

6. Open command prompt and goto project directory and run “mvn install”

7. You should see test will execute and after execution report is generated under directory “\target\cucumber-html-report”. Open index.html file to see the report.

Following are the detailed explanations:

Step 1:  First create a maven eclipse project.

+—src

¦   +—main

¦   ¦   +—java

¦   ¦       +—com

¦   ¦           +—projectname

¦   ¦               +—tests

¦   +—test

¦       +—java

¦           +—com

¦               +—projectname

¦                   +— cucumberrunner

Step 2:  maven pom.xml file has below code:

<project xmlns=http://maven.apache.org/POM/4.0.0&#8221; xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance&#8221;

       xsi:schemaLocation=http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd&#8221;>

       <modelVersion>4.0.0</modelVersion>

       <groupId>CucumberTestNG1</groupId>

       <artifactId>CucumberTestNG1</artifactId>

       <version>0.0.1-SNAPSHOT</version>

       <packaging>jar</packaging>

       <name>CucumberTestNG1</name>

       <url>http://maven.apache.org</url&gt;

       <properties>

              <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

       </properties>

       <build>

              <plugins>

                     <plugin>

                           <groupId>org.apache.maven.plugins</groupId>

                           <artifactId>maven-surefire-plugin</artifactId>

                           <version>2.18.1</version>

                           <configuration>

                                  <suiteXmlFiles>

                                         <suiteXmlFile>resources/testng.xml</suiteXmlFile>

                                  </suiteXmlFiles>

                           </configuration>

                     </plugin>

              </plugins>

       </build>

       <dependencies>

              <dependency>

                     <groupId>org.seleniumhq.selenium</groupId>

                     <artifactId>selenium-java</artifactId>

                     <version>2.50.0</version>

              </dependency>

              <dependency>

                     <groupId>io.appium</groupId>

                     <artifactId>java-client</artifactId>

                     <version>3.3.0</version>

              </dependency>

              <dependency>

                     <groupId>org.testng</groupId>

                     <artifactId>testng</artifactId>

                     <version>6.9.10</version>

              </dependency>

              <dependency>

                     <groupId>info.cukes</groupId>

                     <artifactId>cucumber-testng</artifactId>

                     <version>1.2.4</version>

              </dependency>

              <dependency>

                     <groupId>info.cukes</groupId>

                     <artifactId>cucumber-java</artifactId>

                     <version>1.2.4</version>

                     <scope>test</scope>

              </dependency>

              <dependency>

                     <groupId>info.cukes</groupId>

                     <artifactId>cucumber-jvm</artifactId>

                     <version>1.2.4</version>

                     <type>pom</type>

              </dependency>

              <dependency>

                     <groupId>info.cukes</groupId>

                     <artifactId>cucumber-jvm-deps</artifactId>

                     <version>1.0.5</version>

              </dependency>

              <dependency>

                     <groupId>net.masterthought</groupId>

                     <artifactId>cucumber-reporting</artifactId>

                     <version>1.2.0</version>

              </dependency>

              <dependency>

                     <groupId>info.cukes</groupId>

                     <artifactId>gherkin</artifactId>

                     <version>2.12.2</version>

              </dependency>

              <dependency>

                     <groupId>org.mockito</groupId>

                     <artifactId>mockito-all</artifactId>

                     <version>2.0.2-beta</version>

              </dependency>

              <dependency>

                     <groupId>com.google.guava</groupId>

                     <artifactId>guava</artifactId>

                     <version>18.0</version>

              </dependency>

              <dependency>

                     <groupId>org.hamcrest</groupId>

                     <artifactId>hamcrest-all</artifactId>

                     <version>1.3</version>

              </dependency>

       </dependencies>

</project>

Step 3: Create a feature “googlesearch.feature” file and put into “resources” folder. This file contain below scenario:

Feature: Google Search

  Scenario: Advance Search in Google

    Given user is on google search page

    When enter “journey of quality” text into search field

    And click on search button

    Then verify google logo is “true”

Step 4: Now need to create step definition file for above scenario and implement WebDriver (for Web based applications) or AppiumDriver (for native applications) automation code. So Create a java file “GoogleSearchTest.java” and put under package “com.projectname.tests” of source folder” src/main/java” and write below code:

package com.projectname.tests;

import org.openqa.selenium.By;

import org.openqa.selenium.WebDriver;

import org.openqa.selenium.WebElement;

import org.openqa.selenium.chrome.ChromeDriver;

import org.testng.Assert;

import cucumber.api.java.After;

import cucumber.api.java.Before;

import cucumber.api.java.en.Given;

import cucumber.api.java.en.Then;

import cucumber.api.java.en.When;

public class GoogleSearchTest {

       public static WebDriver driver;

       // Not TestNG annotation and it related to cucumber.api

       @Before

       public void setUp() {

              System.setProperty(

                           “webdriver.chrome.driver”,

                           “E://Softwares//Important tools//selenium-2.44.0//Old Drivers//chromedriver.exe”);

              driver = new ChromeDriver();

              driver.manage().window().maximize();

       }

       // Not TestNG annotation and it related to cucumber.api

       @After

       public void tearDown() {

              // driver.quit();

       }

       // This annotation related to precondition in test execution like

       // @BeforeTest/@BeforeMethod/@BeforeClass

       @Given(“^user is on google search page$”)

       public void user_is_on_google_search_page() throws Throwable {

              driver.get(“https://www.google.co.in/&#8221;);

       }

       // This annotation same as @Test of TestNG, here we are doing actual

       // operation

       @When(“^enter \”([^\”]*)\” text into search field$”)

       public void enter_text_into_search_field(String arg) throws Throwable {

              driver.findElement(By.id(“lst-ib”)).sendKeys(arg);

       }

       // This annotation same as @Test of TestNG, here we are doing actual

       // operation

       @When(“^click on search button$”)

       public void click_on_search_button() throws Throwable {

              driver.findElement(By.id(“sbds”)).click();

       }

       // This annotation related to postcondition in test execution like

       // @AfterTest/@AfterMethod/@AfterClass

       @Then(“^verify google logo is \”([^\”]*)\”$”)

       public void verify_google_logo_is(boolean msg) throws Throwable {

              WebElement message = driver.findElement(By

                           .xpath(“.//*[@id=’logo’]/img”));

              Assert.assertEquals(message.isDisplayed(), msg);

       }

}

Step 5: Now create “Cucumberrun.java” which defines cucumber-jvm configuration and put under package “com.projectname.cucumberrunner” of source folder” src/test/java”.

package com.projectname.cucumberrunner;

import cucumber.api.CucumberOptions;

import cucumber.api.testng.AbstractTestNGCucumberTests;

@CucumberOptions(features = “resources/googlesearch.feature”,

glue = “com.projectname.tests”, format = {

              “html:target/cucumber-html-report”,

              “json:target/cucumber-json-” + “report.json” })

public class Cucumberrun extends AbstractTestNGCucumberTests {

}

Step 6. Open command prompt and goto project directory and run command:

mvn install (or you can directly right click on “pom.xml” and run “Maven install”

Step 7: You should see test will execute and after execution report is generated under directory “\target\cucumber-html-report”. Open index.html file, report should be as below:

Capture

Enjoy your development……………