I am getting java.lang.NullPointerException on onTestFailure to get the screenshot on extent report - nullpointerexception

This was not givving any issue if I call the function by creating the new object and passing the driver but when I made changes to each function to return the object of the next class in page object. then this issue is started appearing.
Listeners file
`
import java.io.IOException;
import org.testng.ITestContext;
import org.testng.ITestListener;
import org.testng.ITestResult;
import com.aventstack.extentreports.ExtentReports;
import com.aventstack.extentreports.ExtentTest;
import com.aventstack.extentreports.Status;
import MobileApp.BillGenratorMobileApp2.Utils.ReusableMethods;
import io.appium.java_client.AppiumDriver;
import io.appium.java_client.android.AndroidDriver;
public class Listeners extends BaseClass implements ITestListener{
AndroidDriver driver;
ExtentReports extent= getExtentReporters.gettreporterObject();
ExtentTest test;
#Override
public void onTestStart(ITestResult result) {
// TODO Auto-generated method stub
ITestListener.super.onTestStart(result);
test= extent.createTest(result.getMethod().getMethodName());
}
#Override
public void onTestSuccess(ITestResult result) {
// TODO Auto-generated method stub
ITestListener.super.onTestSuccess(result);
test.log(Status.PASS ,"Test Pass");
}
#Override
public void onTestFailure(ITestResult result) {
// TODO Auto-generated method stub
ITestListener.super.onTestFailure(result);
test.fail(result.getThrowable());
try {
driver = (AndroidDriver) result.getTestClass().getRealClass().getField("driver").get(result.getInstance());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
test.addScreenCaptureFromPath(getScreenshotPath(result.getMethod().getMethodName(),driver), result.getMethod().getMethodName());
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
`
Base Class file
`
public class BaseClass {
protected AndroidDriver driver;
WebDriver webdriver1;
AppiumDriverLocalService service;
ExtentReports extent;
public String CustomerServiceNo;
public String url;
public final String[] verifyContentInPDf1 = null;
public Properties propConnection = new Properties();
public Dashboard dashboard;
public SideNevigationMenu SideNevigationMenu;
public ReusableMethods ReusableMethods;
public UtiltiyFormStep1 utilityFormsStep1;
public UtilityFormStep2 utilityFormsStep2;
public UtiltiyFormStep3 utilityFormsStep3;
public FlashScreen flashscreen;
public LoginScreen loginScreen;
public W2FormStep1 W2FormStep1;
public W2FormStep2 W2FormStep2;
public W2FormStep3 W2FormStep3;
public W2FormStep4 W2FormStep4;
public W2FormStep5 W2FormStep5;
public W2FormStep6 W2FormStep6;
#BeforeTest
public void configuration() throws IOException {
FileInputStream inputstreemconnection = new FileInputStream(
System.getProperty("user.dir") + "\\src\\main\\java\\MobileApp\\dataResource\\Connection.properties");
FileInputStream inputstreemLoginData = new FileInputStream(
System.getProperty("user.dir") + "\\src\\main\\java\\MobileApp\\dataResource\\LoginData.properties");
FileInputStream inputstreemUtilityData = new FileInputStream(
System.getProperty("user.dir") + "\\src\\main\\java\\MobileApp\\dataResource\\UtilityData.properties");
FileInputStream inputstreemCommonData = new FileInputStream(
System.getProperty("user.dir") + "\\src\\main\\java\\MobileApp\\dataResource\\CommonData.properties");
FileInputStream inputstreemW2Data = new FileInputStream(
System.getProperty("user.dir") + "\\src\\main\\java\\MobileApp\\dataResource\\W2Data.properties");
propConnection.load(inputstreemconnection);
propConnection.load(inputstreemLoginData);
propConnection.load(inputstreemUtilityData);
propConnection.load(inputstreemCommonData);
propConnection.load(inputstreemW2Data);
String port = propConnection.getProperty("Port");
service = new AppiumServiceBuilder()
.withAppiumJS(new File(
"C:\\Users\\Marquee\\AppData\\Roaming\\npm\\node_modules\\appium\\build\\lib\\main.js"))
.withIPAddress(propConnection.getProperty("IPAddress")).usingPort(Integer.parseInt(port)).build();
service.start();
DesiredCapabilities desiredCapabilities = new DesiredCapabilities();
desiredCapabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, "Android");
desiredCapabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, "12");
desiredCapabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator");
desiredCapabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, "uiautomator2");
desiredCapabilities.setCapability("appPackage", "com.example.billgenerator");
desiredCapabilities.setCapability("appActivity", "com.example.billgenerator.MainActivity");
// UiAutomator2Options options = new UiAutomator2Options();
// options.setPlatformName("Android");
// options.setPlatformVersion("12");
// options.setDeviceName("Pixel_2_API_31");
// options.setAutomationName("uiautomator2");
// options.setAppPackage("com.example.billgenerator");
// options.setAppActivity("com.example.billgenerator.MainActivity");
// OR use 127.0.0.1:4723
driver = new AndroidDriver(new URL("http://0.0.0.0:4723"), desiredCapabilities);
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(30));
try {
FileUtils.forceDelete(new File(System.getProperty("user.dir") + "\\reports"));
} catch (IOException e) {
e.printStackTrace();
}
flashscreen = new FlashScreen(driver);
}
public String getScreenshotPath(String testCaseName, AndroidDriver driver) throws IOException {
File source1 = driver.getScreenshotAs(OutputType.FILE);
String destinationfile1 = System.getProperty("user.dir") + "\\reports\\FailTestCasesScreenshots\\"
+ testCaseName + ".png";
FileUtils.copyFile(source1, new File(destinationfile1));
return destinationfile1;
}
The test that got failed.
#Test(priority = 3)
public void verifyCouponCodeFunctionalityWithValidCode() {
SoftAssert softAssertion3 = new SoftAssert();
orderp.enterCoupenCode(propConnection.getProperty("CouponCode"));
nos_calls = orderp.pressApplyCouponButton();
if (orderp.getTotalAmount().equals(" $ 0.0")) {
softAssertion3.assertTrue(true);
} else {
softAssertion3.assertTrue(false, "Coupon not applied");
}
nos_calls += 1;
softAssertion3.assertAll();
}
`
Expecting the extent report to show the screenshot on test failure

Related

ExtentTest class throws null pointer error

Scope(This is what i want to do): Hey looking for to attached screenshot in my extent report file.
Problem: so now i have used the ExtentTest class in BaseClass file. but when i run my testsuit from testNG.xml file, it give me an below error.
java.lang.NullPointerException: Cannot invoke "org.testng.ITestResult.getStatus()" because "com.example.PageClass.BaseClass.result" is null
Here is my Code in BaseClass.
package com.example.PageClass;
import com.example.Utils.Utilities;
import com.relevantcodes.extentreports.ExtentReports;
import com.relevantcodes.extentreports.ExtentTest;
import com.relevantcodes.extentreports.LogStatus;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.PageFactory;
import org.testng.ITestResult;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.time.Duration;
import java.util.Properties;
public class BaseClass {
public static WebDriver driver;
public static Properties prop;
public static LoginPage loginPage;
public static ExtentTest extentTest;
public static ITestResult result;
public static void properties() {
try {
FileInputStream fis = new FileInputStream("src/main/resources/generic.properties");
prop = new Properties();
prop.load(fis);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void setDriver() {
properties();
if (prop.getProperty("browser").contains("chrome")) {
System.setProperty("webdriver.chrome.driver", prop.getProperty("driverPath"));
driver = new ChromeDriver();
} else {
// FirefoxDriverManager.firefoxdriver().setup();
// driver = new FirefoxDriver();
}
driver.get(prop.getProperty("url"));
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(60));
driver.manage().window().maximize();
loginPage = PageFactory.initElements(driver, LoginPage.class);
}
public static void closeDriver() throws IOException {
if (result.getStatus() == ITestResult.FAILURE) {
extentTest.log(LogStatus.FAIL, "TEST CASE FAILED IS " + result.getName()); //to add name in extent report
extentTest.log(LogStatus.FAIL, "TEST CASE FAILED IS " + result.getThrowable()); //to add error/exception in extent report
String screenshotPath = null;
try {
screenshotPath = Utilities.getUtilities().getScreenshot(driver, "firstScreenShot");
} catch (IOException e) {
throw new RuntimeException(e);
}
extentTest.log(LogStatus.FAIL, extentTest.addScreenCapture(screenshotPath)); //to add screenshot in extent report
extentTest.log(LogStatus.PASS, extentTest.addScreenCapture(screenshotPath)); //to add screenshot in extent report
}
driver.quit();
}
}
code inside StepsDef file:
package com.example.StepDefinitions;
import com.example.PageClass.BaseClass;
import com.example.Utils.Utilities;
import com.relevantcodes.extentreports.ExtentTest;
import com.relevantcodes.extentreports.LogStatus;
import io.cucumber.java.After;
import io.cucumber.java.Before;
import io.cucumber.java.en.And;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;
import org.testng.ITestListener;
import org.testng.ITestResult;
import org.testng.annotations.*;
import java.io.IOException;
public class LoginStepDefs extends BaseClass implements ITestListener {
#Before
public void setup(){
setDriver();
}
#After
public void teardown() throws IOException {
closeDriver();
}
#Then("I go to OrangeHRM Home page.")
public void iGoToOrangeHomePage() {
try {
loginPage.getOrangeHRMHome();
} catch (Exception e) {
System.out.println("Username not sent.");
}
}
#When("I enter {string} username and {string} password.")
public void iEnterUsernameAndPassword(String arg0, String arg1) {
try {
loginPage.systemLogin(arg0,arg1);
} catch (Exception e) {
System.out.println("Username not sent.");
}
}
#When("I enter username and password.")
public void iEnterUsernameAndPassword() {
try {
loginPage.systemLogin("Admin","admin123");
} catch (Exception e) {
System.out.println("Username not sent.");
}
}
#And("I navigate to PIM tab and click on add employee.")
public void iNavigateToPIMTabAndClickOnAddEmployee() {
try {
loginPage.clickOnPIM().clickOnAddEmployee();
} catch (Exception e) {
System.out.println("Username not navigate to add employee tab.");
}
}
#And("I enter employee details and save it.")
public void iEnterEmployeeDetailsAndSaveIt() {
try {
loginPage.enterFirstNameAndLastName().fileUpload().checkBoxCreateLoginDetail().enterLoginDetail().verifySuccessMessage().verifySuccessMessageForAdd();
} catch (Exception e) {
System.out.println("Username not navigate to add employee tab.");
}
}
My Folder Structure:
Can Anyone please help me out in this?

NullPointerException error i.e. AndroidDriver not gets initialized for the second test class as It's working fine for the first test class

This is My setup class:
public class SetupClass {
//AppiumDriver<MobileElement> driver;
AndroidDriver<MobileElement> d;
public Properties prop =null;
public File file;
public FileInputStream fis;
#Parameters(value ="Android")
#BeforeSuite
public void setup(String Android) throws IOException, Exception{
LoadPropertiesFile();
DesiredCapabilities caps = new DesiredCapabilities();
/*caps.setCapability("plateformName", "Android");
caps.setCapability(CapabilityType.PLATFORM_NAME, "Android");*/
if (Android.equalsIgnoreCase("Moto_g4_Plus")) {
caps.setCapability(MobileCapabilityType.PLATFORM_NAME, "Android");
caps.setCapability(MobileCapabilityType.PLATFORM_VERSION, "7.0");
caps.setCapability(MobileCapabilityType.UDID, "ZY223WZSQ9");
caps.setCapability(MobileCapabilityType.DEVICE_NAME, "Moto G4 Plus");
}
caps.setCapability("app", "C:\\Users\\amarjeet.sharma\\eclipse-workspace\\com.asm.app\\src\\test\\resources\\app\\asmVisit.apk");
caps.setCapability("appPackage", "com.sumasoft.net.asmscheduler");
caps.setCapability("appActivity", "md5f32326382a711c73d2de951d70f3bd5e.MainActivity");
caps.setCapability("autoGrantPermissions", true);
URL url;
try {
url = new URL("http://127.0.0.1:4723/wd/hub");
//driver = new AppiumDriver<MobileElement>(url, caps);
d = new AndroidDriver<MobileElement>(url, caps);
Thread.sleep(5000);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
System.out.println("Cause is:" +e.getCause());
System.out.println("Message is:" +e.getMessage());
e.printStackTrace();
}
}
public void LoadPropertiesFile() throws IOException {
prop=new Properties();
file =new File(System.getProperty("user.dir")+"/src/main/resources/config.properties");
fis=new FileInputStream(file);
prop.load(fis);
//System.out.println(prop.getProperty("userId"));
}
//#AfterTest
public void TearDown() throws IOException{
System.out.println("Quit");
d.quit();
}
}
This is My LoginTest
public class LoginTest extends SetupClass{
#Test(priority = 1)
public void login() throws Exception {
LoginPage lp = new LoginPage(d);
//System.out.println(prop.getProperty("userId"));
lp.userName(prop.getProperty("userId"));
Thread.sleep(500);
lp.password(prop.getProperty("Passwd"));
Thread.sleep(500);
lp.loginButton();
}
}
And this is my create new journey class
public class AddJourneyTest extends SetupClass{
#Test(priority=2)
public void AddNewJourney() throws Exception {
AddjourneyPage addobj = new AddjourneyPage(d);
addobj.ClicktoAdd();
addobj.SelectFromToDate();
addobj.SelectState();
addobj.SelectCity();
addobj.ClickonSubmit();
}
}
I am getting NullPointerException for AddJourney class
I think when I run it as TestNG then the driver gets initiated for the LoginTest and holds the control. So that AddJourney class does not get driver initiated and hence getting NullPointerException.
I am using Appium Server, Java + Selenium + TestNG for the Android Application automation on Windows system with physical android device.
Maybe I am wrong. But I am not getting solution over it. Please help.

Running Selenium Webdriver tests with TestNG in parallel does not sent correct data to browser

I have two TestNG classes with one test method in each. Each test class has its own #Dataprovider. Each test executes functionality on a web application using Selenium Webdriver. The driver is created for each TestNG class via a factory method and threadlocal so driver should be threadsafe. However when running the tests in parallel using testng.xml the same data is being used across both tests causing one to fail. Here is the code. I'm thinking it might be a problem with the thread safety of the Excel Utility class.
/ DriverFactory
#Listeners(ScreenshotListener.class)
public class DriverFactory {
public final static String URL = "http://localhost/Quotation/Development/index.php";
private static List<WebDriverThread> webDriverThreadPool = Collections.synchronizedList(new ArrayList<WebDriverThread>());
private static ThreadLocal<WebDriverThread> driverThread;
#BeforeClass
public static void instantiateDriverObject() {
System.out.println("Before Class");
driverThread = new ThreadLocal<WebDriverThread>() {
#Override
protected WebDriverThread initialValue() {
WebDriverThread webDriverThread = new WebDriverThread();
webDriverThreadPool.add(webDriverThread);
return webDriverThread;}};
}
#BeforeTest
public void setUp() throws Exception {
System.out.println("Before Test");}
public static WebDriver getDriver() throws Exception {
return driverThread.get().getDriver();}
protected String debug(String methodName) throws Exception {
return methodName + " running on Thread " + Thread.currentThread().getId() +
" with instance as " + this + " and driver " + driverThread.get().getDriver().toString();
}
#AfterSuite
public static void closeDriverObjects() {
System.out.println(webDriverThreadPool.size());
for (WebDriverThread webDriverThread : webDriverThreadPool) {
webDriverThread.quitDriver();}
}
}
// WebDriver thread
public class WebDriverThread {
private WebDriver webdriver;
private DriverType selectedDriverType;
private final DriverType defaultDriverType = FIREFOX;
private final String browser = "CHROME"; //System.getProperty("browser").toUpperCase();
private final String operatingSystem = System.getProperty("os.name").toUpperCase();
private final String systemArchitecture = System.getProperty("os.arch");
private final boolean useRemoteWebDriver = Boolean.getBoolean("remoteDriver");
public WebDriver getDriver() throws Exception {
if (null == webdriver) {
selectedDriverType = determineEffectiveDriverType();
DesiredCapabilities desiredCapabilities = selectedDriverType.getDesiredCapabilities();
instantiateWebDriver(desiredCapabilities);}
return webdriver;}
public void quitDriver() {
if (null != webdriver) {
webdriver.quit();
webdriver = null;
}}
private DriverType determineEffectiveDriverType() {
DriverType driverType = defaultDriverType;
try {
driverType = valueOf(browser);}
catch (IllegalArgumentException ignored) {
System.err.println("Unknown driver specified,defaulting to '" + driverType + "'...");}
catch (NullPointerException ignored) {
System.err.println("No driver specified, defaulting to '" + driverType + "'...");}
return driverType;}
private void instantiateWebDriver(DesiredCapabilities desiredCapabilities) throws MalformedURLException {
System.out.println(" ");
System.out.println("Current Operating System: " + operatingSystem);
System.out.println("Current Architecture: " + systemArchitecture);
System.out.println("Current Browser Selection: " + selectedDriverType);
System.out.println(" ");
if (useRemoteWebDriver) {
URL seleniumGridURL = new URL(System.getProperty("gridURL"));
webdriver = new RemoteWebDriver(seleniumGridURL,desiredCapabilities);
}
else
webdriver = selectedDriverType.getWebDriverObject(desiredCapabilities);
}
}
// ValidLoginTest
public class ValidLoginTest extends DriverFactory{
#BeforeMethod
public void setup() throws Exception {
System.err.println(debug("validLoginTest"));
}
//#Test(dataProvider="ValidLogin" ,dependsOnMethods = { "inValidLoginTest" })
#Test(dataProvider="ValidLogin")
public void validLoginTest(String username, String password, String expectedUserName, String expectedUserEmail) throws Exception {
Login login = new Login();
getDriver().get(URL);
String[] loggedin = login.navigateTo()
.enterUserName(username)
.enterPassword(password)
.andSubmit()
.andCheckLoggedIn();
assertEquals(loggedin[0],expectedUserName);
assertEquals(loggedin[1],expectedUserEmail);
}
#AfterMethod
public void teardown() throws Exception {
JavascriptExecutor jsExecutor = (JavascriptExecutor) getDriver();
jsExecutor.executeScript("sessionStorage.clear();");
}
#DataProvider
public Object[][] ValidLogin() throws Exception{
Object[][] testObjArray = ExcelUtils.getTableArray("SystemTestData.xlsx","ValidLogin");
return (testObjArray);}
}
public class InvalidLoginTest extends DriverFactory{
#BeforeMethod
public void setup() throws Exception {
System.err.println(debug("inValidLoginTest"));
}
#Test(dataProvider="InvalidLogin")
public void inValidLoginTest(String username, String password, String expectedResult) throws Exception {
Login login = new Login();
getDriver().get(URL);
String error = login.navigateTo()
.enterUserName(username)
.enterPassword(password)
.andSubmit()
.andCheckValidation();
assertEquals(error, expectedResult);
login.andClose();
}
#DataProvider
public Object[][] InvalidLogin() throws Exception{
Object[][] testObjArray = ExcelUtils.getTableArray("SystemTestData.xlsx","InvalidLogin");
return (testObjArray);}
}
public class Login {
#FindBy(xpath = "/html/body/nav/div/div[2]/ul/li[3]/a")
private WebElement loginMenu;
#FindBy(name = "user")
private WebElement usernameLocator;
#FindBy(name = "password")
private WebElement passwordLocator;
#FindBy(id = "loginUser")
private WebElement loginUserLocator;
#FindBy(css = "#loginForm > div:nth-child(2) > button:nth-child(2)")
private WebElement closeLocator;
#FindBy(id = "loginError")
private WebElement error;
#FindBy(xpath = "/html/body/nav/div/div[2]/ul/li[3]/ul/li[1]/div/div/div/p[1]/strong")
private WebElement loggedInUserName;
#FindBy(xpath = "/html/body/nav/div/div[2]/ul/li[3]/ul/li[1]/div/div/div/p[2]/strong")
private WebElement loggedInUserEmail;
#FindBy(xpath = "/html/body/nav/div/div[2]/ul/li[3]")
private WebElement account;
private WebDriverWait wait;
public Login() throws Exception {
PageFactory.initElements(DriverFactory.getDriver(), this);
wait = new WebDriverWait(DriverFactory.getDriver(), 30);
System.out.println("Login " + DriverFactory.getDriver().toString());
}
public Login navigateTo() throws Exception {
wait.until(ExpectedConditions.visibilityOf(loginMenu));
loginMenu.click();
return this;
}
public Login enterUserName(String username) {
wait.until(ExpectedConditions.visibilityOf(usernameLocator));
usernameLocator.clear();
for(int i = 0; i < username.length(); i++){
char c = username.charAt(i);
String s = new StringBuilder().append(c).toString();
usernameLocator.sendKeys(s);
}
return this;
}
public Login enterPassword(String password) {
wait.until(ExpectedConditions.visibilityOf(passwordLocator));
passwordLocator.clear();
passwordLocator.sendKeys(password);
return this;
}
public Login andSubmit() {
wait.until(ExpectedConditions.visibilityOf(loginUserLocator));
loginUserLocator.click();
return this;
}
public String[] andCheckLoggedIn() {
String[] actualResult = new String[2];
wait.until(ExpectedConditions.visibilityOf(account));
account.click();
wait.until(ExpectedConditions.visibilityOf(loggedInUserName));
actualResult[0] = loggedInUserName.getText();
actualResult[1] = loggedInUserEmail.getText();
return actualResult;
}
public String andCheckValidation() {
wait.until(ExpectedConditions.visibilityOfAllElements(error));
return error.getText();
}
public void andClose() throws Exception {
wait.until(ExpectedConditions.visibilityOf(closeLocator));
closeLocator.click();
}
}
public class ExcelUtils {
private static XSSFSheet ExcelWSheet;
private static XSSFWorkbook ExcelWBook;
private static XSSFCell Cell;
private static XSSFRow Row;
public static Object[][] getTableArray(String FilePath, String SheetName) throws Exception {
String[][] tabArray = null;
try {
FileInputStream ExcelFile = new FileInputStream(FilePath);
// Access the required test data sheet
ExcelWBook = new XSSFWorkbook(ExcelFile);
ExcelWSheet = ExcelWBook.getSheet(SheetName);
int startRow = 1;
int startCol = 1;
int totalRows = ExcelWSheet.getLastRowNum();
int totalCols = ExcelWSheet.getRow(0).getLastCellNum();
tabArray = new String[totalRows][totalCols -startCol];
for (int row = startRow; row <= totalRows; row++) {
for (int col = startCol; col < totalCols; col++){
tabArray[row - startRow][col - startCol] = getCellData(row, col);
}}}
catch (FileNotFoundException e){
System.out.println("Could not read the Excel sheet");
e.printStackTrace();
}
catch (IOException e){
System.out.println("Could not read the Excel sheet");
e.printStackTrace();
}
return(tabArray);
}
public static String getCellData(int RowNum, int ColNum) throws Exception {
try{
Cell = ExcelWSheet.getRow(RowNum).getCell(ColNum);
if (Cell == null || Cell.getCellTypeEnum() == CellType.BLANK) {
return "";
}else{
String CellData = Cell.getStringCellValue();
return CellData;
}}catch (Exception e){
System.out.println(e.getMessage());
throw (e);
}}}
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="Quotation" parallel="classes" thread-count="3" verbose="1" >
<test name="System Test" >
<classes>
<class name="com.quotation.systemtest.tests.ValidLoginTest"/>
<class name="com.quotation.systemtest.tests.InvalidLoginTest"/>
</classes>
</test>
</suite>
[Testng_Result][1]
[1]: https://i.stack.imgur.com/vLx0y.png

Adding screenshot to the TestNG Report

I'm trying to add Screenshots of the failed test case to the testNG report and I don't have any idea about it
This is my pom class for getting screenshot
package library;
import java.awt.AWTException;
import java.io.File;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
public class TakeScreenShot {
WebDriver driver;
public TakeScreenShot(WebDriver driver) {
this.driver=driver;
}
public void CaptureScreenshot(String screenshotName) throws AWTException
{
try {
TakesScreenshot ts=(TakesScreenshot)driver;
File source=ts.getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(source, new File("C:\\Users\\Documents\\Eclipse\\WorkSpace\\ScreenShot\\"+screenshotName));
System.out.println("Screenshot taken");
} catch (Exception e) {
System.out.println("Exception "+e.getMessage());
}
}
}
And this is my TestNG class
#AfterMethod
public void CloseBrowser(ITestResult result) throws AWTException {
String name=result.getName()+"."+result.getMethod().getCurrentInvocationCount()+".png";
if(ITestResult.FAILURE==result.getStatus())
{
ScreenshotPageObjectModel screenshotPom= new ScreenshotPageObjectModel(driver);
screenshotPom.CaptureScreenshot(name);
}
driver.close();
}
Thanks for helping and please mention where should I do changes for adding the screenshot in the report
You need to use ITestListeners interface of TestNg, it basically provide 7 methods, those are :
onTestStart(ITestResult result)
onTestFailure(ITestResult result)
onTestSuccess(ITestResult result)
onTestSkipped(ITestResult result)
onTestFailedButWithinSuccessPercentage(ITestResult result)
onStart(ITestContext context)
onFinish(ITestContext context)
Your requirement here is "take screen shot of failed test cases/methods".You should use onTestFailure(ITestResult result) methods.
Demonstration :
public class TestListener implements ITestListener {
WebDriver driver=null;
String filePath = "D:\\SCREENSHOTS";
#Override
public void onTestFailure(ITestResult result) {
System.out.println("***** Error "+result.getName()+" test has failed *****");
String methodName=result.getName().toString().trim();
takeScreenShot(methodName);
}
public void takeScreenShot(String methodName) {
//get the driver
driver=TestBase.getDriver();
File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
//The below method will save the screen shot in d drive with test method name
try {
FileUtils.copyFile(scrFile, new File(filePath+methodName+".png"));
System.out.println("***Placed screen shot in "+filePath+" ***");
} catch (IOException e) {
e.printStackTrace();
}
}
public void onFinish(ITestContext context) {}
public void onTestStart(ITestResult result) { }
public void onTestSuccess(ITestResult result) { }
public void onTestSkipped(ITestResult result) { }
public void onTestFailedButWithinSuccessPercentage(ITestResult result) { }
public void onStart(ITestContext context) { }
}
You need to add this tag to your XML file:
<listeners>
<listener class-name="com.pack.listeners.TestListener"/>
</listeners>
To get screen shot use this method:
public static void takeSnapShot(WebDriver driver, String fileWithPath) throws Exception {
TakesScreenshot scrShot = (TakesScreenshot)driver;
File SrcFile = (File)scrShot.getScreenshotAs(OutputType.FILE);
File DestFile = new File(fileWithPath);
FileUtils.copyFile(SrcFile, DestFile);
}
You can call the screen shot under TestNG using below code:
#AfterMethod(
alwaysRun = true
)
protected void afterMethod(ITestResult result, Method method) throws Exception {
// boolean testStatus = false;
String fileName = "FAIL - Error Message Generated on Details Reports";
byte testStatus;
if (result.getStatus() == 2) {
fileName = System.getProperty("user.dir") + "\\Reports\\failure_screenshots\\" + ".png";
takeSnapShot(this.driver, fileName);
ExtentTestManager.getTest().log(LogStatus.FAIL, "Error Screenshot" + ExtentTestManager.getTest().addScreenCapture("failure_screenshots\\" + ".png"));
ExtentTestManager.getTest().log(LogStatus.FAIL, "Test Failed");
testStatus = 2;
} else {
ExtentTestManager.getTest().log(LogStatus.PASS, "Test passed");
testStatus = 1;
}
Ref-> https://www.softwaretestingmaterial.com/screenshots-extent-reports/
http://automationtesting.in/capture-screenshot-in-extent-reports-java/
Hope this helps!!!
PS- Use the most stable extent report version - 2.41.1
I suggest to use ReportNG instead of the TestNG premitive report.

Configuring ExtentReports to provide accurate test statuses and screenshot on failure

I am having some difficulty tweaking ExtentReports to provide the desired output.
I have a simple test framework with TestNG, using a TestBase class to do the heavy lifting to keep tests simple. I wish to implement ExtentReports in a simple fashion, using the TestNG ITestResult interface to report Pass, Fail and Unknown.
Here are example tests, 1 pass and 1 deliberate fail:
public class BBCTest extends TestBase{
#Test
public void bbcHomepagePass() throws MalformedURLException {
assertThat(driver.getTitle(), (equalTo("BBC - Home")));
}
#Test
public void bbcHomePageFail() throws MalformedURLException {
assertThat(driver.getTitle(), (equalTo("BBC - Fail")));
}
And here is the relevant section in TestBase:
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);
}
#BeforeClass
#Parameters({"env", "browser", "login", "mode"})
public void initialiseTests(String env, String browser, String login, String mode) throws MalformedURLException {
EnvironmentConfiguration.populate(env);
WebDriverConfigBean webDriverConfig = aWebDriverConfig()
.withBrowser(browser)
.withDeploymentEnvironment(env)
.withSeleniumMode(mode);
driver = WebDriverManager.openBrowser(webDriverConfig, getClass());
String baseURL = EnvironmentConfiguration.getBaseURL();
String loginURL = EnvironmentConfiguration.getLoginURL();
APPLICATION_LOGS.debug("Will use baseURL " + baseURL);
switch (login) {
case "true":
visit(baseURL + loginURL);
break;
default:
visit(baseURL);
break;
}
driver.manage().deleteAllCookies();
}
#BeforeMethod
public final void beforeTests(Method method) throws InterruptedException {
test = extent.createTest(method.getName());
try {
waitForPageToLoad();
webSessionId = getWebSessionId();
} catch (NullPointerException e) {
APPLICATION_LOGS.error("could not get SessionID");
}
}
#AfterMethod
public void runAfterTest(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: " + webSessionId);
break;
case ITestResult.SKIP:
test.skip(result.getThrowable());
break;
case ITestResult.SUCCESS:
test.pass("Passed");
break;
default:
break;
}
}
private String takeScreenShot(String methodName) {
String path = System.getProperty("user.dir") + "\\test-output\\" + methodName + ".jpg";
try {
File screenshotFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(screenshotFile, new File(path));
} catch (Exception e) {
APPLICATION_LOGS.error("Could not write screenshot" + e);
}
return path;
}
#AfterClass
public void tearDown() {
driver.quit();
}
#AfterSuite()
public void afterSuite() {
extent.flush();
}
Here is the report:
The issues are:
The name of the failed test is not recorded at left hand menu
The screenshot is not displayed despite correctly being taken
It is reporting both a Pass and Unexpected for the passed test
Version 3.0
Most of code is provided by person created this library, i just modified to your needs.
public class TestBase {
private static ExtentReports extent;
private static ExtentTest test;
#BeforeSuite
public void runBeforeEverything() {
String f = System.getProperty("user.dir")+ "/test-output/MyExtentReport.html";
ExtentHtmlReporter h = new ExtentHtmlReporter(f);
extent = new ExtentReports();
extent.attachReporter(h);
}
#BeforeMethod
public void runBeforeTest(Method method) {
test = extent.createTest(method.getName());
}
#AfterMethod
public void runAfterTest(ITestResult result) {
switch (result.getStatus()) {
case ITestResult.FAILURE:
test.fail(result.getThrowable());
test.fail("Screenshot below: " + test.addScreenCaptureFromPath(takeScreenShot(result.getMethod().getMethodName())));
break;
case ITestResult.SKIP:
test.skip(result.getThrowable());
break;
case ITestResult.SUCCESS:
test.pass("Passed");
break;
default:
break;
}
extent.flush();
}
protected String takeScreenShot(String methodName) {
String path = "./screenshots/" + methodName + ".png";
try {
File screenshotFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(screenshotFile, new File(path));
} catch (Exception e) {
APPLICATION_LOGS.error("Could not write screenshot" + e);
}
return path;
}
}
You need several changes to make. Instantiate the ExtentReport & add configuration information in any of the configuration methods except BeforeClass.
#BeforeTest
#Parameters({"env", "browser"})
public void initialiseTests(String env, String browser, String emulatorMode, String mode) {
EnvironmentConfiguration.populate(env);
WebDriverConfigBean webDriverConfig = aWebDriverConfig()
.withBrowser(browser)
.withDeploymentEnvironment(env)
.withSeleniumMode(mode);
driver = WebDriverManager.openBrowser(webDriverConfig, getClass());
APPLICATION_LOGS.debug("Will use baseURL " + EnvironmentConfiguration.getBaseURL());
try {
visit(EnvironmentConfiguration.getBaseURL());
} catch (MalformedURLException e) {
e.printStackTrace();
}
driver.manage().deleteAllCookies();
}
Initailize test = extent.startTest(testName); in the #BeforeMethod section.
#BeforeMethod
public void beforeM(Method m) {
test = extent.startTest(m.getName());
}
And, you may call extent.endTest(test); in the #AfterTest method.
#AfterTest
public void afterTests() {
extent.endTest(test);
extent.close();
}
}
And, to log your step info call test.log(LogStatus, "your info to show"); with appropirate status.