Giter VIP home page Giter VIP logo

testngextentsreport's Introduction

TestNG Extents Report

The TestNG Extents report is a listener plugin which you can add it as a listener to your testng suite to generate a nice Extent report.

This listener uses the ExtentReports v3.0.0, a library developed by Anshoo Arora for reporting.

Build Status

Build Status

Why another library?

You don't have to spend time in re-inventing on how to define what. Just add this as a listener or service loader. You will get the nice looking report generated at the end of your test execution.

Also, you will get the emailable report out-of-the box.

Pre-requisite

  • JDK 8+
  • Extent Report v3.0.2+

Usage

For maven, add the following as dependency:

<dependency>
    <groupId>com.vimalselvam</groupId>
    <artifactId>testng-extentsreport</artifactId>
    <version>1.3.1</version>
</dependency>

Either in your testng.xml, add the listener:

<listeners>
    <listener class-name="com.vimalselvam.testng.listener.ExtentTestNgFormatter" />
</listeners>

or add as a service loader (recommended).

By default, the report will be generated at TestNG's output directory. i.e., test-output/report.html and the emailable report at test-output/emailable-report.html.

In case you want to generate the report in a different location, make sure you pass the JVM argument called reportPath with the absolute directory path.

For example: I run my maven test as: mvn clean test -DreportPath=output. This will generate both the reports in the ${project directory}/output.

Adding custom reporter config

You can customize the report using a XML file. The XML file should follow as given here: ExtentReports Configuration.

The XML file should be referred as parameter in your suite xml. The parameter name should be report.config. For instance, the parameter in the suite xml should be as follows:

<parameter name="report.config" value="src/test/resources/extent-config.xml" />

The value should be the config XML file path.

Adding System Information

In case you want to add system information, you will have to implement an interface com.vimalselvam.testng.SystemInfo. This interface contains a method with return type as Map<String, String>. Construct your system information with the map and return that map. After you have implemented, the custom implementation should be referred in your TestNG Suite xml as a parameter at the suite level.

For instance add the following parameter at your suite level in the TestNG suite xml:

<parameter name="system.info" value="test.MySystemInfo" />

The parameter name should be system.info and the value should be your fully qualified custom implementation class name. For example my custom implementation look like this:

package test;

import com.vimalselvam.testng.SystemInfo;
import org.testng.collections.Maps;

import java.util.Map;

/**
 * This is a small utility class to prepare the system information
 */
public class MySystemInfo implements SystemInfo {
    @Override
    public Map<String, String> getSystemInfo() {
        Map<String, String> systemInfo = Maps.newHashMap();
        systemInfo.put("Test Env", "QA");
        systemInfo.put("Browser", "firefox");
        return systemInfo;
    }
}

Instance of the Listener

At any point in time, you can get the instance of the listener as ExtentTestNgFormatter.getInstance()

Adding Screenshot

To add the screenshot, you have two options.

  • If the screenshot can be added from the test method, then
ExtentTestNgFormatter.getInstance().addScreenCaptureFromPath(filePath);
  • If the screenshot can be added from the configuration method, then for example:
@AfterMethod
public void afterMethod(ITestResult iTestResult) throws IOException {
    // The ITestResult is a mandatory parameter
    ExtentTestNgFormatter.getInstance().addScreenCaptureFromPath(iTestResult, filePath);
}

Adding info log

If any case, you want to attach the info log on your test method, you simply call TestNg's Reporter.log method which will be added to your test log. For example:

@Test
public void testMethod() {
    Reporter.log("Custom log");
}

Adding test runner output

To add the test runner output, simply call from anywhere:

ExtentTestNgFormatter.getInstance().setTestRunnerOutput("My output");

Adding new node

Sometimes you may have to add new node under your test. This situation arises when you have iteration in the test method and considering each iteration as a separate node in the report. This could be solved by using addNewNodeToTest() method.

Refer DemoTestClass on how to add new nodes and in case of failure, how to fail the added node.

Cucumber?

Refer my another library which generates the same report for the cucumber based BDD tests: CucumberExtentReporter

testngextentsreport's People

Contributors

email2vimalraj avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

testngextentsreport's Issues

Preventing generation of Emailable Report

I would like to know if there any configuration to avoid generation of emailable-report.html by default.

Also is it possible to configure the emailable-report.html template?

I just want to create the regular extend report.

ExtentReport showing screenshot in encrypted format

Hi,

Extent Report is showing embedded screenshot in encrypted format. I have encoded the same using Base64. When I try opening screenshot it is showing junk characters in encrypted format. Can you please look into it.

Thanks in advance

  • Viswa

Providing reportPath via code

I would like to know if it's possible to pass the reportPath value from the code.. for example in @BeforeClass or @BeforeSuite methods..

The output path depends on the maven profile and I would like to control the path from my code.

BTW, good work on this plugin. Works like a charm.

How to create a node at class level

Hi Vimal,

First of all thanks for creating a sample listener which is very useful. But i'm stuck in a small issue.
I want to create a node at class level. I'm using the listener as follows

    @Override
public void onStart(ITestContext iTestContext) {
	ISuite iSuite = iTestContext.getSuite();
	ExtentTest suite = (ExtentTest) iSuite.getAttribute(SUITE_ATTR);
	ExtentTest testContext = suite.createNode(iTestContext.getName());
	iTestContext.setAttribute("testContext", testContext);
	System.out.println("ClassName is : " + returnClassName(iTestContext));
}

@Override
public void beforeInvocation(IInvokedMethod iInvokedMethod,
		ITestResult iTestResult) {
	ITestNGMethod method = iInvokedMethod.getTestMethod();
	System.out.println("Class Name Inside before Invocation Method: "
			+ returnClassName(method));
	if (iInvokedMethod.isTestMethod()) {
		ITestContext iTestContext = iTestResult.getTestContext();
		ExtentTest child = (ExtentTest) iTestContext
				.getAttribute("testContext");
		cNode = child.createNode(returnMethodName(iInvokedMethod
				.getTestMethod()));
		iTestResult.setAttribute("test", cNode);
		String textMsg = "About to begin executing following method : "
				+ "<b>" + returnMethodName(iInvokedMethod.getTestMethod())
				+ "</b>";
		Reporter.log(textMsg, true);
	}
}

@Override
public void afterInvocation(IInvokedMethod iInvokedMethod,
		ITestResult iTestResult) {
	if (iInvokedMethod.isTestMethod()) {
		ExtentTest test = (ExtentTest) iTestResult.getAttribute("test");
		List<String> logs = Reporter.getOutput(iTestResult);

		for (String log : logs) {
			test.info(log);
		}

		int status = iTestResult.getStatus();
		if (ITestResult.SUCCESS == status) {
			test.pass("Passed");
		} else if (ITestResult.FAILURE == status) {
			test.fail(iTestResult.getThrowable());
		} else if (ITestResult.SKIP == status) {
			test.skip(iTestResult.getThrowable());
		} else {
			Reporter.log("Please check the script..!!");
		}
		for (String group : iInvokedMethod.getTestMethod().getGroups()) {
			test.assignCategory(group);
		}
		String textMsg = "Test executing of : " + "<b>"
				+ returnMethodName(iInvokedMethod.getTestMethod()) + "</b>"
				+ " is completed ";
		Reporter.log(textMsg, true);
	}

}

@Override
public void onFinish(ITestContext iTestContext) {
	ExtentTest testContext = (ExtentTest) iTestContext
			.getAttribute("testContext");
	if (iTestContext.getFailedTests().size() > 0) {
		testContext.fail("Failed");
	} else if (iTestContext.getSkippedTests().size() > 0) {
		testContext.skip("Skipped");
	} else {
		testContext.pass("Passed");
	}
	
}

This report is giving all the methods inside tag in xml.

Xml that am using is:

I want to create a node when a tag is encountered.
Any help would be really helpful. Looking forward for your reply.

Thanks & Regards,
Sandeep.

Is it possible to send the report via mail but in the body of the email and not as attachment or without the CSS?

I've tried using the extent report before and it generates me a good rich UI for reports. While sending the reports from jenkins i see the report being sent as an attachment. Another try i gave and it was successful in sending the email via body but this time the CSS was missing and only the HTML stuff was visible. Looked so pathetic :( . Since then I didnt find anything good on internet so that the CSS gets visible in the body

Adding ExtentCucumberFormatter plugin in testrunner file failed to create new TestNGCucumberRunner(this.getClass()); object

This works well when i dont add "com.cucumber.listener.ExtentCucumberFormatter:target/cucumber-reports/report.html" plugin in my TestRunner file. But as soon as i add this plugin it failed to create this object testNGCucumberRunner = new TestNGCucumberRunner(this.getClass());

Could you please suggest what am i doing wrong here!

@CucumberOptions(features= {"src\test\resources\FunctionalTests"},
glue= {"stepDefinitions"},
plugin = {"pretty",
"html:target/html/",
"json:target/json/file.json",
"com.cucumber.listener.ExtentCucumberFormatter:target/cucumber-reports/report.html"

},
strict=false,
dryRun=false,
monochrome = true,
tags= "@test"
)

public class TestRunner{
private TestNGCucumberRunner testNGCucumberRunner;

@parameters({"browsername"})
@BeforeClass(alwaysRun = true)
public void setUpClass(String browsername) throws Exception {

testNGCucumberRunner = new TestNGCucumberRunner(this.getClass()); 
 Reporter.loadXMLConfig(new File("src\\test\\resources\\extent-config.xml"));

}

@test(groups = "cucumber", description = "Runs Cucumber Scenarios", dataProvider = "scenarios")
public void scenario(PickleWrapper pickle, FeatureWrapper cucumberFeature) throws Throwable {
testNGCucumberRunner.runScenario(pickle.getPickle());
}
@dataProvider
public Object[][] scenarios() {
return testNGCucumberRunner.provideScenarios();
}
@afterclass(alwaysRun = true)
public void tearDownClass() throws Exception{

testNGCucumberRunner.finish();
}

TestNG: java.lang.NoSuchMethodError: com.aventstack.extentreports.ExtentTest.assignCategory([Ljava/lang/String;)Lcom/aventstack/extentreports/ExtentTest

TestNG Version

Note: only the latest version is supported
7.8.0

ExtentReport Version

Note: only the latest version is supported
3.3.0

Expected behavior

Should be able to execute test in parallel with testNG attributes groups and dependsOnGroups

Actual behavior


java.lang.NoSuchMethodError: com.aventstack.extentreports.ExtentTest.assignCategory([Ljava/lang/String;)Lcom/aventstack/extentreports/ExtentTest;

	at com.vimalselvam.testng.listener.ExtentTestNgFormatter.afterInvocation(ExtentTestNgFormatter.java:193)
	at org.testng.internal.invokers.InvokedMethodListenerInvoker$InvokeAfterInvocationWithoutContextStrategy.callMethod(InvokedMethodListenerInvoker.java:100)
	at org.testng.internal.invokers.InvokedMethodListenerInvoker.invokeListener(InvokedMethodListenerInvoker.java:62)
	at org.testng.internal.Invoker.runInvokedMethodListeners(Invoker.java:566)
	at org.testng.internal.Invoker.invokeMethod(Invoker.java:713)
	at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:869)
	at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1193)
	at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:126)
	at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:109)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)

Is the issue reproducible on runner?

  • Shell
  • Maven
  • Gradle
  • Ant
  • Eclipse
  • IntelliJ
  • NetBeans

Test case sample

Please, share the test case (as small as possible) which shows the issue

ReportsTest.java

import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

public class ReportsTest extends GenericTest {
    private GenericController genericController;
    private ReportsController reportsController;

    @BeforeMethod
    public void beforeMethodReports(){
        genericController = new GenericController(selDriver);
        reportsController = new ReportsController(selDriver);
    }

    @Test(dataProvider = "testA", dataProviderClass = DataProviderCustom.class, groups = {"Reports"})
    public void testA(String dataTestCaseName, ReportModel reportModel){
        try {
            // Setup

            // Trigger

            // Assertion

        } catch (Exception ex) {
            Utilities.printUnexpectedPageErrors(selDriver, dataTestCaseName, ex);
        }
    }

}

FileUploadTest.java

import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

public class ReportsTest extends GenericTest {
    private GenericController genericController;
    private ReportsController reportsController;

    @BeforeMethod
    public void beforeMethodReports(){
        genericController = new GenericController(selDriver);
        reportsController = new ReportsController(selDriver);
    }

    @Test(dataProvider = "testB", dataProviderClass = DataProviderCustom.class, groups = {"FileUpload"}, dependsOnGroups = {"Reports"})
    public void testB(String dataTestCaseName, ReportModel reportModel){
        try {
            // Setup

            // Trigger

            // Assertion

        } catch (Exception ex) {
            Utilities.printUnexpectedPageErrors(selDriver, dataTestCaseName, ex);
        }
    }

}

suite.xml

<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Selenium Webdriver Test" parallel="classes" thread-count="3">
    <listeners>
        <listener class-name="com.vimalselvam.testng.listener.ExtentTestNgFormatter" />
    </listeners>
    <test name="Test in FF">
        <classes>
            <class name="com.sample.test.FileUploadTest">
                <methods>
                    <include name="testA"/>
                </methods>
            </class>
            <class name="com.sample.test.ReportsTest">
                <methods>
                    <include name="testA" />
                </methods>
            </class>
        </classes>
    </test>
</suite>

Time stamp is not updating correctly for each Reporter.log step

Hi Vimal, Thanks for your listener which make easy way for creating report.
I am running the following code as Maven project, Extent report generating is generating, but Timestamp is not updating properly for each Reporter.log step.

package test;

import org.testng.ITestResult;
import org.testng.Reporter;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.Test;

import java.io.IOException;

/**

  • This is a sample TestNG test.
    */
    public class TestNgTest {
    @AfterMethod
    public void afterMethod(ITestResult iTestResult) throws IOException {
    Reporter.log("After Method: " + iTestResult.getMethod().getMethodName());
    }

    @test(groups = {"group1"})
    public void simpleTest() {
    Reporter.log("Simple test", true);
    Reporter.log("Simple test");
    Reporter.log("Another log");
    }

    @test(groups = {"group2"})
    public void anotherSimpleTest() {
    Reporter.log("Another Simple test");
    }
    }

Timestamp is same for all the steps shown in below.

Status Timestamp Details
info_outline 3:32:50 PM Simple test
info_outline 3:32:50 PM Simple test
info_outline 3:32:50 PM Another log
check_circle 3:32:50 PM Passed

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.