Sunday 21 October 2018

Extent Reporting with Selenium

Selenium reporting using Extent Report and TestNG

Many of us working on automation using Selenium Webdriver to reduce the time and cost and achieve higher percentage of test coverage. Along with this, there needs to have advance reporting which gives us details information of particular test run.


So, Extent report is very high in demand and popular which is being used with Selenium. And we all know, TestNG generates HTML report by default which is not more readable and attractive. We have to put lots of efforts to make it attractive. But this has been provided an ability to implement "IReporter an interface to customize TestNG report.


Extent Report API makes our life easy to generate interactive report with simple configuartion.
Considering you have Maven project created..

Step 1 - Extent Report Maven Dependency :

<dependency>      <groupId>com.aventstack</groupId>      <artifactId>extentreports</artifactId>      <version>3.1.5</version> </dependency>


Step 2 - Add extent report classes.


ExtentManager Class:

package utils.ExtentReports; import com.relevantcodes.extentreports.ExtentReports; public class ExtentManager { private static ExtentReports extent; public synchronized static ExtentReports getReporter(){ if(extent == null){ String workingDir = System.getProperty("user.dir"); //Configure HTML report file location extent = new ExtentReports(workingDir+"\\ExtentReports\\ExtentReport.html", true); } return extent; } }

ExtentTestManager Class:

- Here we are going to create extentTestMap will hold the information.

Instance is created by calling getReporter() method from ExtentManager.

- At StartTest() method, an instance of ExtentTest created and put into extentTestMap with current thread id.

At EndTest() method, test ends and ExtentTest instance obtained from extentTestMap via current thread id.

At getTest() method, return ExtentTest instance in extentTestMap by using current thread id.



package utils.ExtentReports; import com.relevantcodes.extentreports.ExtentReports; import com.relevantcodes.extentreports.ExtentTest; import java.util.HashMap; import java.util.Map; public class ExtentTestManager { static Map extentTestMap = new HashMap(); static ExtentReports extent = ExtentManager.getReporter(); public static synchronized ExtentTest getTest() { return (ExtentTest)extentTestMap.get((int) (long) (Thread.currentThread().getId())); } public static synchronized void endTest() { extent.endTest((ExtentTest)extentTestMap.get((int) (long) (Thread.currentThread().getId()))); } public static synchronized ExtentTest startTest(String testName, String desc) { ExtentTest test = extent.startTest(testName, desc); extentTestMap.put((int) (long) (Thread.currentThread().getId()), test); return test; } }


TestListener Class:


package utils.Listeners; import com.relevantcodes.extentreports.LogStatus; import org.openqa.selenium.OutputType; import org.openqa.selenium.TakesScreenshot; import org.openqa.selenium.WebDriver; import org.testng.ITestContext; import org.testng.ITestListener; import org.testng.ITestResult; import tests.BaseTest; import utils.ExtentReports.ExtentManager; import utils.ExtentReports.ExtentTestManager; public class TestListener extends BaseTest implements ITestListener { private static String getTestMethodName(ITestResult iTestResult) { return iTestResult.getMethod().getConstructorOrMethod().getName(); } //Before starting all tests, below method runs. @Override public void onStart(ITestContext iTestContext) { System.out.println("I am in onStart method " + iTestContext.getName()); iTestContext.setAttribute("WebDriver", this.driver); } //After ending all tests, below method runs. @Override public void onFinish(ITestContext iTestContext) { System.out.println("I am in onFinish method " + iTestContext.getName()); //Do tier down operations for extentreports reporting! ExtentTestManager.endTest(); ExtentManager.getReporter().flush(); } @Override public void onTestStart(ITestResult iTestResult) { System.out.println("I am in onTestStart method " + getTestMethodName(iTestResult) + " start"); //Start operation for extentreports. ExtentTestManager.startTest(iTestResult.getMethod().getMethodName(),""); } @Override public void onTestSuccess(ITestResult iTestResult) { System.out.println("I am in onTestSuccess method " + getTestMethodName(iTestResult) + " succeed"); //Extentreports log operation for passed tests. ExtentTestManager.getTest().log(LogStatus.PASS, "Test passed"); } @Override public void onTestFailure(ITestResult iTestResult) { System.out.println("I am in onTestFailure method " + getTestMethodName(iTestResult) + " failed"); //Get driver from BaseTest and assign to local webdriver variable. Object testClass = iTestResult.getInstance(); WebDriver webDriver = ((BaseTest) testClass).getDriver(); //Take base64Screenshot screenshot. String base64Screenshot = "data:image/png;base64,"+((TakesScreenshot)webDriver). getScreenshotAs(OutputType.BASE64); //Extentreports log and screenshot operations for failed tests. ExtentTestManager.getTest().log(LogStatus.FAIL,"Test Failed", ExtentTestManager.getTest().addBase64ScreenShot(base64Screenshot)); } @Override public void onTestSkipped(ITestResult iTestResult) { System.out.println("I am in onTestSkipped method "+ getTestMethodName(iTestResult) + " skipped"); //Extentreports log operation for skipped tests. ExtentTestManager.getTest().log(LogStatus.SKIP, "Test Skipped"); } @Override public void onTestFailedButWithinSuccessPercentage(ITestResult iTestResult) { System.out.println("Test failed but it is in defined success ratio " + getTestMethodName(iTestResult)); }

AnnotationTransformer Class:

package utils.Listeners; import org.testng.IAnnotationTransformer; import org.testng.annotations.ITestAnnotation; import java.lang.reflect.Constructor; import java.lang.reflect.Method; public class AnnotationTransformer implements IAnnotationTransformer { @Override public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) { annotation.setRetryAnalyzer(Retry.class); } } 


Retry Class:

package utils.Listeners; import com.relevantcodes.extentreports.LogStatus; import org.openqa.selenium.OutputType; import org.openqa.selenium.TakesScreenshot; import org.openqa.selenium.WebDriver; import org.testng.IRetryAnalyzer; import org.testng.ITestResult; import tests.BaseTest; import utils.ExtentReports.ExtentTestManager; public class Retry implements IRetryAnalyzer { private int count = 0; private static int maxTry = 1; //Run the failed test 2 times @Override public boolean retry(ITestResult iTestResult) { if (!iTestResult.isSuccess()) { if (count < maxTry) { count++; iTestResult.setStatus(ITestResult.FAILURE); extendReportsFailOperations(iTestResult); return true; } } else { iTestResult.setStatus(ITestResult.SUCCESS); } return false; } public void extendReportsFailOperations (ITestResult iTestResult) { Object testClass = iTestResult.getInstance(); WebDriver webDriver = ((BaseTest) testClass).getDriver(); String base64Screenshot = "data:image/png;base64,"+((TakesScreenshot)webDriver).getScreenshotAs(OutputType.BASE64); ExtentTestManager.getTest().log(LogStatus.FAIL,"Test Failed", ExtentTestManager.getTest().addBase64ScreenShot(base64Screenshot)); }


Step 4 - Add description

@Test (priority=1, description="Scenario of providing empty username and password")
public void invliadTest()
{
ExtentTestManager.getTest().setDescription("Scenario of providing empty username and password");


Step 5 - Adding listener to TestNG.xml file

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd"> <suite name="N11 Test Suite" > <listeners> <listener class-name="utils.Listeners.TestListener"/> <listener class-name="utils.Listeners.AnnotationTransformer"/> </listeners> <test name="LoginTest"> <classes> <class name="tests.LoginTests"/> </classes> </test> </suite>


Step 6 - BaseTest Class

package tests; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.support.ui.WebDriverWait; import org.testng.annotations.AfterClass; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; public class BaseTest { public WebDriver driver; public WebDriverWait wait; public WebDriver getDriver() { return driver; } @BeforeClass public void setup () { driver = new ChromeDriver(); wait = new WebDriverWait(driver,15); driver.manage().window().maximize(); } @AfterClass public void teardown () { driver.quit(); } }


Step 7 - Test Class

package tests; import org.testng.annotations.Test; import pages.HomePage; import pages.LoginPage; import utils.ExtentReports.ExtentTestManager; public class LoginTests extends BaseTest { @Test (priority = 0, description="Scenario of providing empty username and password") public void invalidLoginTest_InvalidUserNameInvalidPassword () throws InterruptedException { //ExtentReports Description ExtentTestManager.getTest().setDescription("Scenario of providing empty username and password"); HomePage homePage = new HomePage(driver,wait); LoginPage loginPage = new LoginPage(driver,wait); homePage.goToN11(); //Go to LoginPage homePage.goToLoginPage(); //Login to N11 loginPage.loginToN11("onur@swtestacademy.com", "11223344"); //*************ASSERTIONS*********************** Thread.sleep(500); loginPage.verifyLoginPassword(("password")); } @Test (priority = 1, description="Scenario of providing empty username and password") public void invalidLoginTest_EmptyUserEmptyPassword () throws InterruptedException { //ExtentReports Description ExtentTestManager.getTest().setDescription("Scenario of providing empty username and password"); //*************PAGE INSTANTIATIONS************* HomePage homePage = new HomePage(driver,wait); LoginPage loginPage = new LoginPage(driver,wait); //*************PAGE METHODS******************** homePage.goToN11(); homePage.goToLoginPage(); loginPage.loginToN11("",""); //*************ASSERTIONS*********************** Thread.sleep(500); loginPage.verifyLoginUserName("username"); loginPage.verifyLoginPassword("password"); } }


After all this, run the test and you will see html file generated under ExtentReport folder as shown below...or under test-output accordingly. When you open the result you will see test result as shown below:





--------------------------------------------------------------------

3 comments:

Select Language