A Testers blog
  • Home
  • About me
Follow

ExtentReports review

Aug26
2015
21 Comments Written by Richard Kieft

Yesterday I was asked to add some kind of reporting to our selenium test suite. I had some ideas to create a report in excel, but this all ended up in having to write a lot of code and probably reinventing the wheel. After some time using google I came across the website of Bas Dijkstra where he was reviewing ExtentReport version 1.4. Before reading the rest of my post you might want to read this post. After reading I became pretty exited about this library! Next I went to see the website of the creator of ExtentReports, ReleventCodes.com. I installed the latest version (at the time 2.04) by adding it to my maven pom.xml and gave it a go. Below my approach and some tips.

Installation:

For installation I used maven. Add the following to the pom.xml of your test project:

<dependency>
    <groupId>com.relevantcodes</groupId>
    <artifactId>extentreports</artifactId>
    <version>2.04</version>
</dependency>

Open your command prompt and navigate to where ever your pom.xml is located and execute the following command:

mvn install -DskipTests
And your ready to go!

Using Junit? Use a @Rule annotation!

Since we already developed a “complete” automation test suite I didn’t want to add a new reporting line after every test we have written. When your experimenting with this library you could do this but later on you probably want to put this on a higher level in your testsuite.
First of all I want to tell you a little about the testsuite. I’m using Selenium webdriver (Java) and I developed our suite using the PageObjectPattern. I wrote a baseTestClass and all other tests extend this class. The baseTestClass responsibility is to setup Selenium (start a browser, navigating to a URL, truncate a database, etc.) I wrote a screenshotTaker class earlier which makes a screenshot of the browser when the test fails. This screenshotTakerClass has been added as a rule to the baseTestClass. This seems like a good starting point for me to see if a test fails if it creates a report and how it looks. For now I just added a line of code to the “failed” method of this specific class:

BaseTestClass snippet:
See line 11 for the rule where we call on the screenshotTakerClass

public class BaseTestclass {

	public static WebDriver driver;	
	/*
	 * Set some properties as a member.
	*/	
	private static String screenshotLocatie;
	private static String browser;
	
	@Rule
    public ScreenshotTaker screenShootRule = new ScreenshotTaker(driver, screenshotLocatie);

	@BeforeClass
	public static void setup() throws Exception {
		getProperties();
		
		//empty the database before testing.
		resetDatabase();
		if ("Firefox".equals(browser)) {
			driver = new FirefoxDriver();
		} else if("InternetExplorer".equals(browser)) {
			driver = new InternetExplorerDriver();
		} else {
			//fallback when browser propertie is not set to firefox.
			driver = new FirefoxDriver();			
		}
		//set the browser to max size
		driver.manage().window().maximize();
	}
}

screenshotTakerClass:


public class ScreenshotTaker extends TestWatcher {
    private WebDriver browser;
    private String screenshotLocation;
	private String filenameOfReport= "C:/myReportingDir/testReport" + DateTimeHelper.getDateOfToday() + ".html";
    
    public ScreenshotTaker(WebDriver browser, String screenshotLocatie) {
        this.browser =  browser;
        this.screenshotLocation =  screenshotLocation;
    }

    @Override
    protected void failed(Throwable e, Description description) {
        TakesScreenshot takesScreenshot = (TakesScreenshot) browser;

        File scrFile = takesScreenshot.getScreenshotAs(OutputType.FILE);
        File destFile = getDestinationFile(description);
        try {
            FileUtils.copyFile(scrFile, destFile);
        } catch (IOException ioe) {
            throw new RuntimeException(ioe);
        }
        ExtentReports extent = createReport();
        ExtentTest test = extent.startTest(description.getDisplayName(), "Test failed, click here for further details");

		// step log
		test.log(LogStatus.FAIL, "Failure trace Selenium: "+ e.toString());
		flushReports(extent, test);
    }
    
    //When passed only write to the log.
    @Override
    protected void succeeded(Description description) {
		ExtentReports extent = createReport();
         ExtentTest test = extent.startTest(description.getDisplayName(), "-");

 		// step log
 		test.log(LogStatus.PASS, "-");
 		flushReports(extent, test);
    }

    private ExtentReports createReport() {
    	ExtentReports extent = new ExtentReports(filenameOfReport, false);
        extent.config().reportName("My first extentReport report");
        extent.config().reportHeadline("See my awesome passed tests!");
        return extent;
    }
    
    private void flushReports(ExtentReports extent, ExtentTest test){
    	// ending test
 		extent.endTest(test);
 		// writing everything to document
 		extent.flush();
    }
    
    private File getDestinationFile(Description description) {
        String userDirectory = screenshotLocation;
        String date = getDateTime();
        String fileName = description.getDisplayName() + "_" + date + ".png";
        //add date of today
        String dateForDir = DateTimeHelper.getDateOfToday();
        String absoluteFileName = userDirectory + "/" + dateForDir + "/" + fileName;

        return new File(absoluteFileName);
    }
    
    private String getDateTime() {
    	Date date = Calendar.getInstance().getTime();

        // Display a date in day, month, year format
        DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy_HH_mm_ss");
        String today = formatter.format(date);
        return today;
    }
}

After adding this to existing screenshotTakerClass I let JUnit run a complete test of our testsuite.
Every single test we have is added to the report, passed or failed!

Because I do not have to add a log line after every test I have to pass on the name of the test to identify the failing (or passed) test.
I came to this line (see line 23 and 34 in the code above)

ExtentTest test = extent.startTest(description.getDisplayName(), "Description of the test here....");

In the report it will show up as methodName(packageName) (for example: myAwsomeTest(com.mytestproject.seleniumtests.mostawesometests).

Next thing I wanted is to show the failure trace to see what went wrong:
I added this line:

test.log(LogStatus.FAIL, "Failure trace Selenium: "+ e.toString());

This one only applies to the failure, when a test is passed I don’t need any more information then it is passed:

test.log(LogStatus.PASS, "-");

After experimenting a little bit with ExtentReports I changed the reporting name to make it more suitable to the test project.

extent.config().reportName("Selenium - Awesome project");
extent.config().reportHeadline("Overview of testresults");

That’s it for now! After this modifications the report suited just fine for me. Only thing left is to rename the screenshotTakerClass since it now has more responsibilities.
I think EventReports is a very nice library to use when you have the need to build reports for Selenium. It will probably also fit other Java based test tools.

For more detailed information and other possibilities in Extend reports see:
http://extentreports.relevantcodes.com/2x/docs.html

Questions? Please leave a comment below!

Posted in Testing
SHARE THIS Twitter Facebook Delicious StumbleUpon E-mail
← Back to blogging again!
Agile/SCRUM make your daily standup more effective →

20 Comments

  1. purnima's Gravatar purnima
    October 30, 2015 at 1:26 pm | Permalink

    Hi,
    I am using Junit and Cucumber-JVM. I have added the @Rule in my baseTest.class. And have a screenshotTaker class, but it doesn’t seem to initiate the Extent class, so it’s throwing java.lang.nullpointer exception.

    Reply
    • Richard Kieft's Gravatar Richard Kieft
      October 30, 2015 at 3:27 pm | Permalink

      Hi,

      Thnx for your reply.
      Could you provide me some example of your code?

      Best Regards,

      Richard

      Reply
      • Manjunath's Gravatar Manjunath
        May 1, 2016 at 8:33 am | Permalink

        Hi,

        Any update on extent report for Cucumber-JVM.

        Reply
        • Richard Kieft's Gravatar Richard Kieft
          May 1, 2016 at 5:51 pm | Permalink

          Hi,

          Sorry, I have no idea.
          Please keep track on http://extentreports.relevantcodes.com/java/ for more information.
          Its not my project 😉

          Reply
  2. Kyle's Gravatar Kyle
    November 18, 2015 at 3:39 pm | Permalink

    I was wondering how the tests knows if it fails or passes?

    Reply
  3. Santosh's Gravatar Santosh
    January 7, 2016 at 3:53 pm | Permalink

    HI,
    Richard Kieft i am using junit and wondering how you have set up your Testsuite. will it be possible for you to share your testsuite code.

    Reply
  4. puneet jain's Gravatar puneet jain
    January 18, 2016 at 7:43 pm | Permalink

    Hi,

    How will i used extent report in key word-driven frame work? .

    As in framework there are 3 or more step against each test cases. so will i implement this in such a way that each test case content it test steps in hierarchy way.

    below piece of code return the result for test cases parent0 only. not for parent 1 and parent 2.

    public static void main(String arg[])
    {
    ExtentReports extent=new ExtentReports(“./demo.html”);

    ExtentTest parent=null;

    for(int i=0;i<3;i++){

    parent = extent.startTest("Parent"+i);

    for(int j=i;i<3;i++){

    ExtentTest child1 = extent.startTest("Child 1");
    child1.log(LogStatus.INFO, "Info from method"+j);

    parent
    .appendChild(child1);

    }
    extent.endTest(parent);
    extent.flush();

    }
    }

    Please have a look.

    Thank,
    Puneet Jain

    Reply
  5. jayagopi's Gravatar jayagopi
    April 15, 2016 at 12:55 pm | Permalink

    hi,

    Thanks for the short, concise and easily digestable code on how to use EntentReports 🙂

    The link to the ExtentReports documentation does not work. Tried many times.
    May I have the correct url please ?
    Thanks.
    Jay

    Reply
    • Richard Kieft's Gravatar Richard Kieft
      May 1, 2016 at 5:46 pm | Permalink

      Hi Jay,

      I think you are looking for this one:
      http://extentreports.relevantcodes.com/java/

      Best Regards,

      Richard

      Reply
  6. jayagopi's Gravatar jayagopi
    April 20, 2016 at 11:04 am | Permalink

    well, never mind.
    i found it : http://extentreports.relevantcodes.com/java/#examples

    My webdriver tests are also based on the page object pattern and yes, i too use the JUnit TestWatcher class to trap the failed/succeeded tests.
    I added the code for ExtentReports similar to your code and get a wonderful report.
    But I did notice that the times for the tests in the report are wrong ( starttime/endtime/total time taken etc ). I am using ExtentReports v2.40.2 and JUnit 4.4.
    Have you noticed that ? In your code you don’t give the test start/end time to ExtenReports. Does it get it from the JUnit framework runner automatically ?
    cheers,
    jay

    Reply
  7. jayagopi's Gravatar jayagopi
    April 20, 2016 at 12:30 pm | Permalink

    ok. looks like one needs to set the test start/end times explicitly in the ExtentTest object in order to get the correct times in the final report.
    see the testStartTime and testEndTime being set in the code below.

    here is my example :

    package fi.lahitapiola.henkivakuutus.junit.rule;

    import java.io.File;
    import java.util.Calendar;
    import java.util.Date;
    import java.util.Properties;

    import org.junit.rules.TestWatcher;
    import org.junit.runner.Description;
    import org.openqa.selenium.OutputType;
    import org.openqa.selenium.TakesScreenshot;
    import org.openqa.selenium.WebDriver;

    import com.cgi.testing.jay.reporting.Reporting;
    import com.relevantcodes.extentreports.ExtentReports;
    import com.relevantcodes.extentreports.ExtentTest;
    import com.relevantcodes.extentreports.LogStatus;
    import fi.lahitapiola.henkivakuutus.pageobjects.ErrorIstuntoVanhentunutPage;
    import fi.lahitapiola.henkivakuutus.pageobjects.ErrorTechnicalPage;
    import fi.lahitapiola.henkivakuutus.utils.PropertiesHandler;
    import fi.lahitapiola.henkivakuutus.utils.Utils;

    public class RikuTestWatcher extends TestWatcher {

    private static String REPORT_FILENAME = “C:/temp/extentreports.html”;
    private final Reporting reporting;
    private final WebDriver driver;
    private static boolean stopTesting = false;
    private static final Properties testProps = PropertiesHandler.getTestEnvProperties();
    private Date testStartTime = null;
    private Date testEndTime = null;

    public RikuTestWatcher( WebDriver driver ) {

    super();
    this.driver = driver;
    reporting = new Reporting( REPORT_FILENAME, driver );
    testStartTime = Calendar.getInstance().getTime();

    }

    public static boolean shouldStopTesting() {
    return stopTesting;
    }

    @Override
    protected void failed( Throwable t, Description desc ) {

    System.out.println(“RikuTestWatcher.failed(): entered”);
    System.out.println(“RikuTestWatcher.failed(): test failed: method ” + desc.getMethodName() +
    “, exception class ” + t.getClass().getSimpleName() );
    System.out.println(“RikuTestWatcher.failed(): exception reason: ” + t.getMessage() );

    processForErrorPage( driver );
    processForIstuntoVanhentunutPage( driver );
    String scrShotFilename = takeScreenShot( driver );

    stopTesting = true;

    ExtentReports extent = reporting.createReport();
    ExtentTest test = extent.startTest( desc.getDisplayName(), “Test failed, click here for further details” );

    testEndTime = Calendar.getInstance().getTime();
    test.setStartedTime( testStartTime );
    test.setEndedTime( testEndTime );

    test.log( LogStatus.FAIL, “Test method : ” + desc.getMethodName(), t.toString() );
    test.log( LogStatus.FAIL, “Failed page screenshot : “, test.addScreenCapture(scrShotFilename ) );

    reporting.close( extent, test );

    System.out.println(“RikuTestWatcher.failed(): adding screen shot image to Extent reports :” + scrShotFilename );
    System.out.println(“RikuTestWatcher.failed(): exiting”);

    }

    @Override
    protected void succeeded( Description desc ) {

    System.out.println(“RikuTestWatcher.succeeded(): entered”);
    System.out.println(“RikuTestWatcher.succeeded(): test passed: method ” + desc.getMethodName() );

    ExtentReports extent = reporting.createReport();
    ExtentTest test = extent.startTest( desc.getDisplayName(), “-” );

    testEndTime = Calendar.getInstance().getTime();
    test.setStartedTime( testStartTime );
    test.setEndedTime( testEndTime );

    test.log( LogStatus.PASS, “Test method : ” + desc.getMethodName(), “-” );

    if ( testProps != null ) {
    test.log( LogStatus.PASS,
    “Test method : ” + desc.getMethodName(),
    “Henkivakuutus interface file : ”
    );
    }

    reporting.close( extent, test );

    System.out.println(“RikuTestWatcher.succeeded(): exiting”);

    }

    private void processForErrorPage( WebDriver driver ) {

    ErrorTechnicalPage erPage = new ErrorTechnicalPage( driver );
    erPage.displayVirheInfo();

    }

    private void processForIstuntoVanhentunutPage( WebDriver driver ) {

    ErrorIstuntoVanhentunutPage erPage = new ErrorIstuntoVanhentunutPage( driver );
    erPage.displayVirheInfo();

    }

    private String takeScreenShot( WebDriver driver ) {

    File inScrShotFile = ( (TakesScreenshot)driver ).getScreenshotAs( OutputType.FILE );
    if ( inScrShotFile == null ) {
    System.out.println(“RikuTestWatcher.takeScreenShot() : webdriver failed to take screenshot of the current webpage” );
    return “***”;
    }

    File outScrShotFile = new File( “c:\\temp\\webdriver-scrshot-” + System.currentTimeMillis() + “.png” );
    String scrShotFilename = outScrShotFile.getAbsolutePath();
    System.out.println(“——————————————————————————————-“);
    System.out.println(“RikuTestWatcher.takeScreenShot() : writing screenshot to file : ” + scrShotFilename );
    System.out.println(“——————————————————————————————-“);
    Utils.copyBytes( inScrShotFile, outScrShotFile );
    return scrShotFilename;

    }

    }

    Reply
    • Babu's Gravatar Babu
      November 14, 2016 at 5:01 pm | Permalink

      Hello,
      I having an error “The method setEndedTime(Date) is undefined for the type ExtentTest” once I use following steps to get the execution time.
      test.setStartedTime( testStartTime );
      test.setEndedTime( testEndTime );

      Reply
  8. Ak's Gravatar Ak
    May 17, 2016 at 6:31 am | Permalink

    Hi Richard,

    Can you please tell me step by step that how we can create this extent reports by using above solution ?
    My tests are developed in Junit.

    Reply
    • Richard Kieft's Gravatar Richard Kieft
      May 17, 2016 at 11:20 am | Permalink

      Hi,

      ok, Do you have something like a basetestclass?
      I have one and each other tests extends from this class.
      Basically the basetestclass sets up everything a selenium needs, browser, database properties, login, etc.
      By annotating the basetestclass with the @rule annotation all testclasses automatically will be reported in the extend test report whenever it passes or fails.

      Reply
      • Ak's Gravatar Ak
        May 18, 2016 at 9:43 am | Permalink

        Hi Richard,

        Thanks for your reply,
        No , But I’m not having baseclass to operate all setting singular.

        My structure of project is –
        All the test scripts are separately written in junit test
        This all tests are called using – one class (test suite class)

        I need your help , Let me know if we can have a skype call / chat

        Reply
        • Richard Kieft's Gravatar Richard Kieft
          May 18, 2016 at 1:07 pm | Permalink

          Can’t just simply put the @rule annotation in the test suite class?
          I can see a reason why it shouldn’t work….
          Could you try?

          Reply
          • Ak's Gravatar Ak
            May 19, 2016 at 5:18 am | Permalink

            I have tried in a way you have mentioned i.e. putting @rule annotation in the
            class , even it has provided me result but that result does not contain test cases names it contains only testsuite name.

            Can i share my code with you ?
            Could you please provide me email-id where we can communicate?

            Many Thanks !
            Ak

          • Ak's Gravatar Ak
            May 23, 2016 at 5:15 am | Permalink

            Hi Richard,

            Can you please provide me help here.

            Akshay

  9. Ak's Gravatar Ak
    May 17, 2016 at 9:59 am | Permalink

    Can anybody please tell me , How to implement this?

    Reply
  10. Abhishek Gupta's Gravatar Abhishek Gupta
    March 1, 2017 at 11:41 am | Permalink

    Thank you so much, this was of much help!

    Reply
  1. ExtentReports for Awesome Selenium WebDriver Reporting on August 26, 2015 at 2:36 pm

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Recent Comments

  • Abhishek Gupta on ExtentReports review
  • Babu on ExtentReports review
  • Ak on ExtentReports review
  • Ak on ExtentReports review
  • Richard Kieft on ExtentReports review

Archives

  • February 2016 (1)
  • August 2015 (1)
  • May 2012 (3)

Links

  • Software testing club

EvoLve theme by Theme4Press  •  Powered by WordPress A Testers blog