How to use screeshotcapture in IReporter interface in Selenium using TestNG? - java

I am using IReporter TestNG interface in Selenium, but how to capture screenshot and add in Extent Report for failed test-case ?
Please help me to find the solution.

Below is the code for attaching failed test case screenshots to the Extent Report.
MyReporterClass implements IReporter interface: It iterates over the test cases in the test suite and saves the status for each test case.
public class MyReporterClass implements IReporter {
#Override
public void generateReport(List<XmlSuite> xmlSuites, List<ISuite> suites, String outputDirectory) {
//Iterating over each suite included in the test
for (ISuite suite : suites) {
//Following code gets the suite name
String suiteName = suite.getName();
//Getting the results for the said suite
Map<String, ISuiteResult> suiteResults = suite.getResults();
for (ISuiteResult sr : suiteResults.values()) {
ITestContext tc = sr.getTestContext();
System.out.println("Passed tests for suite '" + suiteName +
"' is:" + tc.getPassedTests().getAllResults().size());
System.out.println("Failed tests for suite '" + suiteName +
"' is:" + tc.getFailedTests().getAllResults().size());
System.out.println("Skipped tests for suite '" + suiteName +
"' is:" + tc.getSkippedTests().getAllResults().size());
}
}
}
}
getScreenshot() method: To capture the screenshot and return the destination path for the screenshot.
public class ExtentReportsClass{
public static String getScreenshot(WebDriver driver, String screenshotName) throws Exception {
//below line is just to append the date format with the screenshot name to avoid duplicate names
String dateName = new SimpleDateFormat("yyyyMMddhhmmss").format(new Date());
TakesScreenshot ts = (TakesScreenshot) driver;
File source = ts.getScreenshotAs(OutputType.FILE);
//after execution, you could see a folder "FailedTestsScreenshots" under src folder
String destination = System.getProperty("user.dir") + "/FailedTestsScreenshots/"+screenshotName+dateName+".png";
File finalDestination = new File(destination);
FileUtils.copyFile(source, finalDestination);
//Returns the captured file path
return destination;
}
}
#AfterMethod
public void getResult(ItestResult result): It is executed after each test case execution and attaches the failed test case screenshot to Extent report.
#AfterMethod
public void getResult(ITestResult result) throws IOException{
if(result.getStatus() == ITestResult.FAILURE){
logger.log(LogStatus.FAIL, "Test Case Failed is "+result.getName());
logger.log(LogStatus.FAIL, "Test Case Failed is "+result.getThrowable());
//To capture screenshot path and store the path of the screenshot in the string "screenshotPath"
String screenshotPath = ExtentReportsClass.getScreenshot(driver, result.getName());
//To add it in the extent report
logger.log(LogStatus.FAIL, logger.addScreenCapture(screenshotPath));
}else if(result.getStatus() == ITestResult.SKIP){
logger.log(LogStatus.SKIP, "Test Case Skipped is "+result.getName());
}
testng.xml file : Include the below listener tag in the xml file .
<listeners>
<listener class-name="packagename.MyReporterClass" />
</listeners>

Related

Extent Reports 4 - Java

Trying to generate one extent report, that will allow me to run a suite of test classes and give output as one report.
My current code below runs fin, it will run my testNG.xml file and successfully run all test classes in my suite. THe extent report itself however, only seems to save the last test cases run to it. I can't for the life of me figure out how to stop it overwriting, and append to it instead. Older version of extent report uses htmlreporter.setAppendExisting(true); but that does not exist in extent 4..
public class ExtentManager {
ExtentHtmlReporter htmlReporter;
ExtentReports extent;
ExtentTest parentTest;
ExtentTest childTest;
DriverManager driverManager;
WebDriver driver;
Screenshot screenshot;
Properties config;
String timeStamp = new SimpleDateFormat("yyyy.MM.dd.HH.mm.ss").format(new Date());
/** Suite test as it will run, with Before/After instructions*/
#BeforeTest
public void beforeTest() throws IOException {
/**Create extent reports and configure html report*/
htmlReporter = new ExtentHtmlReporter(".//reports/ExtentReport"+timeStamp+".html");
extent = new ExtentReports();
extent.attachReporter(htmlReporter);
htmlReporter.config().setTheme(Theme.DARK);
htmlReporter.config().setDocumentTitle("Automation Testing");
htmlReporter.config().setReportName("My Report");
htmlReporter.config().setAutoCreateRelativePathMedia(true);
htmlReporter.config().setTimeStampFormat("HH:mm:ss");
screenshot = new Screenshot();
config = new Properties();
FileInputStream fis = new FileInputStream(System.getProperty("user.dir") + "/src/main/resources/Config.properties");
config.load(fis);
}
public ExtentReports getExtent(){
if(extent != null){
return this.extent;
} else {
return new ExtentReports();
}
}
#BeforeClass
public void beforeClass() {
/**Setup parent test, all child tests to follow
*will attach to it for html report*/
extent = getExtent();
parentTest = extent.createTest(getClass().getSimpleName());
driverManager = new DriverManager();
driver = driverManager.getWebDriver();
driver.manage().timeouts().pageLoadTimeout(15, TimeUnit.SECONDS);
}
#AfterMethod
public void getResult(ITestResult result) throws IOException {
if (result.getStatus() == ITestResult.SUCCESS){
childTest.log(Status.PASS, MarkupHelper.createLabel("Test Case: " + result.getName() + " PASSED", ExtentColor.GREEN));
}else if(result.getStatus() == ITestResult.FAILURE){
String screenshotPath = screenshot.getScreenshot(driver, result.getName());
childTest.log(Status.FAIL, MarkupHelper.createLabel("Test Case: " + result.getName() + " FAILED", ExtentColor.RED));
childTest.fail(result.getThrowable().getMessage());
childTest.log(Status.WARNING, "Error screenshot captured and stored # " + screenshotPath);
childTest.addScreenCaptureFromPath(screenshotPath);
}else if(result.getStatus() == ITestResult.SKIP){
childTest.log(Status.SKIP, MarkupHelper.createLabel("Test Case: " + result.getName() + " SKIPPED", ExtentColor.AMBER));
childTest.log(Status.SKIP, "Skipped test: " + result.getName());
}
}
#AfterTest
public void afterTest(){
driverManager.quitWebDriver();
}
#AfterSuite
public void afterSuite() {
extent.flush();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="sanity_tests" parallel="false" verbose="10">
<test name="test1" parallel="false" preserve-order="true" verbose="10">
<classes>
<class name="com.testFramework.Tests.test1"/>
</classes>
</test>
<test name="test2" parallel="false" preserve-order="true" verbose="10">
<classes>
<class name="com.testFramework.Tests.test2"/>
</classes>
</test>
</suite>
you can use the Extent report adapters and with that there is no need to write any code, check the below article out. In your case- you will need to use the TestNG adapter-
Try this: https://www.linkedin.com/pulse/extent-framework-adapters-anshoo-arora/`

Configuring ExtentReports to inject custom html

I need my Extent Report (v 3.0.0) to have a hyperlink in the page. I am trying to inject the custom HTML for the following, where webSessionID is a UUID I scrape from the webpage.
The URL format should be:
OPY5Q2EV3P:6CBA845DB3E99F97931FCC9ED84711EB
Here is what I am trying (note code comments for relevant areas):
My code:
public class TestBase implements Config {
protected WebDriver driver = null;
private Logger APPLICATION_LOGS = LoggerFactory.getLogger(getClass());
private static ExtentReports extent;
private static ExtentTest test;
private static ITestContext context;
private static String webSessionId;
#BeforeSuite
#Parameters({"env", "browser"})
public void beforeSuite(String env, String browser) {
String f = System.getProperty("user.dir") + "\\test-output\\FabrixExtentReport.html";
ExtentHtmlReporter h = new ExtentHtmlReporter(f);
extent = new ExtentReports();
extent.attachReporter(h);
extent.setSystemInfo("browser: ", browser);
extent.setSystemInfo("env: ", env);
String codeBlockOne = "<a href=" + "\"https://myapp.com/app/logs/s/\"";
String codeBlockTwo = "/a>";
m1 = MarkupHelper.createCodeBlock(codeBlockOne); //SET HTML OPENING
m2 = MarkupHelper.createCodeBlock(codeBlockTwo); //SET HTML CLOSING
}
#AfterMethod
public void afterMethod(ITestResult result) throws IOException {
switch (result.getStatus()) {
case ITestResult.FAILURE:
test.fail(result.getThrowable());
test.fail("Screenshot below: " + test.addScreenCaptureFromPath(takeScreenShot(result.getMethod().getMethodName())));
test.fail("WebSessionId: " + m1 + webSessionId + m2);//RELEVANT METHOD
break;
case ITestResult.SKIP:
test.skip(result.getThrowable());
break;
case ITestResult.SUCCESS:
test.pass("Passed");
break;
default:
break;
}
}
Current output of the relevant tag is:
<td class='step-details'>WebSessionId:
com.aventstack.extentreports.markuputils.CodeBlock#432038ectfbweb0~FE5625464A1F6ED331FB2355BDAF8F00com.aventstack.extentreports.markuputils.CodeBlock#7daa0fbd</ td>
</tr>
Not familiar with ER but you are just getting string representation of Markup object reference. m1 = MarkupHelper.createCodeBlock(codeBlockOne); m1 will have Markup type. Try to use m1.getMarkup().

how to create custom reports in testng

I have the following Java code:
public class Login {
String Login_Status = null;
String Login_Message = null;
#Test
#Parameters({"USERNAME","PASSWORD"})
public void Execute(String UserName, String Password) throws IOException {
try {
Config.driver.findElement(By.linkText("Log in")).click();
Config.driver.findElement(By.id("user_login")).sendKeys(UserName);
Config.driver.findElement(By.id("user_pass")).sendKeys(Password);
Config.driver.findElement(By.id("wp-submit")).click();
// perform validation here
boolean expvalue = Config.driver.findElement(By.xpath("//a[#rel='home']")).isDisplayed();
if (expvalue) {
Login_Status = "PASS";
Login_Message="Login Successfull for user:" + UserName + ",password:" + Password + ",\n EXPECTED: rtMedia Demo Site LINK SHOULD BE PRESENT ON THE HOME PAGE OF rtMedia ACTUAL: rtMedia LINK is PRESENT ON THE HOME PAGE OF rtMedia. DETAILS:NA";
}
} catch(Exception generalException) {
Login_Status = "FAIL";
Login_Message = "Login UnSuccessfull for user:" + UserName + ",password:" + Password + ",\n EXPECTED: rtMedia Demo Site LINK SHOULD BE PRESENT ON THE HOME PAGE OF rtMedia ACTUAL: rtMedia LINK is NOT PRESENT ON THE HOME PAGE OF rtMedia. DETAILS:Exception Occurred:"+generalException.getLocalizedMessage();
// File scrFile = ((TakesScreenshot) Config.driver).getScreenshotAs(OutputType.FILE);
// FileUtils.copyFile(scrFile, new File("C:\\Users\\Public\\Pictures\\failure.png"));
} finally {
Assert.assertTrue(Login_Status.equalsIgnoreCase("PASS"), Login_Message);
}
}
}
I wrote the above Java code for login functionality and now I want to create reports for whatever the result will be (pass or fail) and it should be stored in folder? I have no idea about the generating the reports and also I found the reports are automatically generated by TestNG itself but when we run another test it gets overwritten, that will not help for me. Any help?
There are quite a few ways you can achieve this
If you're using XML report then you can implement IReporter and create a listener. You have to override a method called generateReport(List<XmlSuite> xmlSuites, List<ISuite> suites, String outputDirectory) and you can have your own logic to save the output in a different folder everytime you run the test case.
There is an attribute in testNG called fileFragmentationLevel if you set it to 3 I think your report will not be overwritten. It's in XML reporter class
You can create a listener that will extend TestListenerAdapter and override onStart(ITestContext testContext) method to back up your testoutput folder everytime. But I don't prefer this method.
I prefer #1.

Create Custom TestNG Report - WebDriver

I'm trying to implement org.testng IReporter Interface. My Java is not that great, base on some example I found online I was able to create a Reporter class. The problem I'm having is how to use it and where do I call it and how and which parameters to pass to it?
public class Reporter implements IReporter {
public void generateReport(List<XmlSuite> xmlSuites, List<ISuite> suites, String outputDirectory){
ISuiteResult results =suites.get(0).getResults().get("Sanity Suite");
ITestContext context = results.getTestContext();
IResultMap passedTests = context.getPassedTests();
IResultMap failedTests = context.getFailedTests();
// Print all test exceptions...
for( ITestResult r: failedTests.getAllResults()) {
System.out.println( r.getThrowable());
}
}
}
For example I have this WebDriver Selenium TestNG test:
public class VerifyTest extends TestBase {
#Test
public void test1() {
verifyTrue(false);
verifyEquals("pass", "fail");
verifyFalse(true);
}
#Test
public void test2() {
verifyTrue(false);
assertEquals("pass", "fail");
verifyFalse(true);
}
How would I use my Reporter to get a customize report at the end of the run???
Thank You!
Just expand your skeleton above to generate your results where you want them, .xml, .html, text file, etc...
David, you can add your custom reporter to your testng.xml in case you are invoking your tests through an xml in the suite section.
<listeners>
<listener class-name="yourpackage.Reporter"/> </listeners>
In case you are programmatically invoking those, then you need to add it through your code as documented # Running TestNG programmatically
If you are invoking your tests from command line, refer this
This reporter would be invoked by TestNG at then end of all the runs, if you specify in either of the above ways.
I created a project that is an example of generating a customized report.
The basic idea is to create a Listener class and reference it in the testing.xml file.
<listeners>
<listener class-name="qa.hs.framework.CustomReportListener"/>
</listeners>
And then create the class:
public class CustomReportListener implements IReporter {
#Override
public void generateReport( List<XmlSuite> xmlSuites, List<ISuite> suites,
String outputDirectory ) {
System.out.println();
//Iterating over each suite included in the test
for (ISuite suite : suites) {
//Following code gets the suite name
String suiteName = suite.getName();
//Getting the results for the said suite
Map<String, ISuiteResult> suiteResults = suite.getResults();
for ( ISuiteResult sr : suiteResults.values() ) {
ITestContext tc = sr.getTestContext();
System.out.println("Passed tests for suite '" + suiteName + "' is:" +
tc.getPassedTests().getAllResults().size());
}
CustomReport cr = new CustomReport();
cr.generateReport( xmlSuites, suites, outputDirectory );
...
Then, from that Listener class you can create a "Report Writer" class that creates any arbitrary HTML output using something like so:
public class CustomReport extends CustomReportListener
{
private static final Logger LOG = Logger.getLogger( CustomReport.class );
private static final SimpleDateFormat dateFormatter = new SimpleDateFormat(" MMM d 'at' hh:mm a");
private String reportFileName = Constants.reportFileName;
private PrintWriter m_out;
private int m_row;
private Integer m_testIndex;
private int m_methodIndex;
private Scanner scanner;
#Override
public void generateReport( List<XmlSuite> xml, List<ISuite> suites, String outdir ) {
try {
m_out = createWriter( outdir );
}
catch ( IOException e ) {
LOG.error("output file", e);
return;
}
startHtml(m_out);
generateSuiteSummaryReport(suites);
generateMethodSummaryReport(suites);
generateMethodDetailReport(suites);
endHtml(m_out);
m_out.flush();
m_out.close();
}
And finally, from that "CustomReport" class your "generate report" methods all have access to all data from the report, such as:
testContext.getPassedTests()
Map<String, ISuiteResult> r = suite.getResults()
method.getDescription()
method.getTestClass().getName()
ITestResult.SUCCESS
tests.getAllMethods()
overview.getStartDate().getTime()
overview.getIncludedGroups()
etc.
You can use
#Listeners(ReporterClassName.class)
ex:
#Listeners(Reporter.class)
public class VerifyTest extends TestBase
Beautiful reporting with realtime report of any running test is possible using RealTime report plugin. Very easy to use and no modification needed in existing code, for details please visit this github url RealTimeReport
You can find details implementation of different TestNg Reporting intrfaces

How can I include a failure screenshot to the testNG report

currently I am taking screenshots of my test failures this way:
#AfterMethod(alwaysRun=true)
public void catchExceptions(ITestResult result){
Calendar calendar = Calendar.getInstance();
SimpleDateFormat formater = new SimpleDateFormat("dd_MM_yyyy_hh_mm_ss");
String methodName = result.getName();
if(!result.isSuccess()){
File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
try {
FileUtils.copyFile(scrFile, new File((String) PathConverter.convert("failure_screenshots/"+methodName+"_"+formater.format(calendar.getTime())+".png")));
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
Can I include my own screenshots into the TestNG report link or pic? If yes how?
All I found on that online is the FEST framework. But since I am already taking the screenshots I dont want to use another framework.
Yes, you can include the link to your screenshot in testng report.
You need to call org.testng.Reporter.log method to write the hyperlink to the testng report either by annotating your test class or parent of all testclasses with #Listeners({yourListener.class}) or by adding the listener to your testng.xml.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="default">
<listeners>
<listener class-name="ScreenshotListener" />
</listeners>
<test name="Test">
<packages>
<package name="someTests.*"/>
</packages>
</test>
</suite>
You need to first create a Listener class and add it to testng. You can get details for that from testng.org. Search for listener.
Once you create that class, you should write a method in it which overrides the ontestfailure method. The code inside this method will be executed whenever testng identifies a failure.
You can call your screenshot grabbing method and use Reporter.log to put the hyperlink to that screenshot. Then you can find this link under the failed testcases details.
import java.io.*;
import java.util.*;
import java.text.*;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.*;
import org.testng.*;
public class ScreenshotListener extends TestListenerAdapter {
#Override
public void onTestFailure(ITestResult result) {
Calendar calendar = Calendar.getInstance();
SimpleDateFormat formater = new SimpleDateFormat("dd_MM_yyyy_hh_mm_ss");
String methodName = result.getName();
if(!result.isSuccess()){
File scrFile = ((TakesScreenshot)SomeStaticWebDriver.driver).getScreenshotAs(OutputType.FILE);
try {
String reportDirectory = new File(System.getProperty("user.dir")).getAbsolutePath() + "/target/surefire-reports";
File destFile = new File((String) reportDirectory+"/failure_screenshots/"+methodName+"_"+formater.format(calendar.getTime())+".png");
FileUtils.copyFile(scrFile, destFile);
Reporter.log("<a href='"+ destFile.getAbsolutePath() + "'> <img src='"+ destFile.getAbsolutePath() + "' height='100' width='100'/> </a>");
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Customizing a bit of ExtentReport can give extremely useful report having exception+screenshot captured exactly at time of test failure . Screenshot can be placed alongside exception which user can use to know what was website doing when error occurred.
Report Example
Test
#Test (enabled=true)
public void verifySearch() {
extentlogger = extent.createTest("To verify verifySearch");
//Your other code here.....
soft.assertEquals("xxx", "xxxx");
soft.assertAll();
}
AfterMethod
#AfterMethod
public void getResult(ITestResult result) throws Exception{
if(result.getStatus() == ITestResult.FAILURE)
{
extentlogger.log(Status.FAIL, MarkupHelper.createLabel(result.getThrowable() +
" - Test Case Failed", ExtentColor.RED));
try {
// get path of captured screenshot using custom failedTCTakeScreenshot method
String screenshotPath = failedTCTakeScreenshot( result);
extentlogger.fail("Test Case Failed Snapshot is below " +
extentlogger.addScreenCaptureFromPath(screenshotPath));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

Categories

Resources