I have a maven project that runs testng and cucumber. If I run the testng and my test fails my program takes screenshots and creates a report. However if I run my cucumber tests and it fails, I get java.lang.NullPointerException: Cannot invoke "org.openqa.selenium.TakesScreenshot.getScreenshotAs(org.openqa.selenium.OutputType)" because "screenShot" is null
.
Both the testng and cucumber references the same listeners and base class.
My listeners class (on failure):
@Override
public void onTestFailure(ITestResult result) {
ExtentThred.get().fail(result.getThrowable());
WebDriver driver = null;
String testMethodName = result.getMethod().getMethodName();
try {
driver = (WebDriver)result.getTestClass().getRealClass().getDeclaredField("driver").get(result.getInstance());
}
catch (Exception e)
{
}
try {
ExtentThred.get().addScreenCaptureFromPath(getScreenshotPath(testMethodName, driver),result.getMethod().getMethodName());
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
My base class:
public class Base {
public static WebDriver driver;
public Properties prop;
public WebDriver initializeDriver() throws IOException {
prop = new Properties();
FileInputStream file = new FileInputStream(System.getProperty("user.dir") + "\\src\\main\\java\\resources\\data.properties");
prop.load(file);
String browserName = prop.getProperty("browser");
if (browserName.contains("chrome")) {
System.setProperty("webdriver.chrome.driver", System.getProperty("user.dir") + "\\chromedriver.exe");
ChromeOptions chromeOptions = new ChromeOptions();
if (browserName.contains("headless")){
chromeOptions.addArguments("headless");
}
driver = new ChromeDriver(chromeOptions);
}
else if (browserName == "firefox") {
}
else if (browserName == "edge") {
}
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
return driver;
}
public String getScreenshotPath(String testCaseName, WebDriver driver) throws IOException
{
TakesScreenshot screenShot = (TakesScreenshot) driver;
File source = screenShot.getScreenshotAs(OutputType.FILE);
String destinationFile = System.getProperty("user.dir")+"\\reports\\"+ testCaseName +".png";
FileUtils.copyFile(source, new File(destinationFile));
return destinationFile;
}
}
My testng class that works fine:
public class ValidateLoggedIn extends Base {
public WebDriver driver;
@BeforeTest
public void initialize() throws IOException {
driver = initializeDriver();
}
@Test(dataProvider = "getData")
public void HomePageTitle(String mobileNumber, String password, String access) throws IOException {
driver.get(prop.getProperty("cars"));
MainPage mainPage = new MainPage(driver);
mainPage.getLogin().click();
mainPage.getMobileNumber().sendKeys(mobileNumber);
mainPage.getPassword().sendKeys(password);
mainPage.getLoginButton().click();
if (access == "Allowed User") {
LoggedInPage loggedInPage = new LoggedInPage(driver);
Assert.assertTrue(loggedInPage.getLogOutButton().isDisplayed());
loggedInPage.getLogOutButton().click();
}
else {
mainPage.getLoginButton();
Assert.assertTrue(mainPage.getLoginButton().isDisplayed());
}
}
@DataProvider
public Object[][] getData() {
Object[][] userData = new Object[1][3];
userData[0][0] = "0720127992";
userData[0][1] = "Dr0medar!s";
userData[0][2] = "Allowed User";
return userData;
}
@AfterTest
public void teardown()
{
driver.close();
}
}
My step definition for my cucumber:
public class StepDefinition extends Base {
public WebDriver driver;
@Given("^Initilize the browser with Chrome$")
public void initilize_the_browser_with_chrome() throws Throwable {
driver = initializeDriver();
}
@When("^User enters (.+) and (.+) and logs in$")
public void user_enters_and_and_logs_in(String mobilenumber, String password) throws Throwable {
MainPage mainPage = new MainPage(driver);
mainPage.getLogin().click();
mainPage.getMobileNumber().sendKeys(mobilenumber);
mainPage.getPassword().sendKeys(password);
mainPage.getLoginButton().click();
}
@Then("^verify if user is successfully logged in$")
public void verify_if_user_is_successfully_logged_in() throws Throwable {
LoggedInPage loggedInPage = new LoggedInPage(driver);
Assert.assertTrue(loggedInPage.getLogOutButton().isDisplayed());
loggedInPage.getLogOutButton().click();
}
@And("^Navigate to \"([^\"]*)\" site$")
public void navigate_to_something_site(String strArg1) throws Throwable {
driver.get(strArg1);
}
@And("^Close Browser$")
public void close_browser() throws Throwable {
driver.quit();
}
}
My test runner:
@CucumberOptions(
features = "src/test/java/features",
glue = "stepDefinitions")
public class TestRunner extends AbstractTestNGCucumberTests {
}
My error:
java.lang.NullPointerException: Cannot invoke "org.openqa.selenium.TakesScreenshot.getScreenshotAs(org.openqa.selenium.OutputType)" because "screenShot" is null
at resources.Base.getScreenshotPath(Base.java:53)
at cars.Listeners.onTestFailure(Listeners.java:52)
at org.testng.internal.TestListenerHelper.runTestListeners(TestListenerHelper.java:96)
at org.testng.internal.TestInvoker.runTestResultListener(TestInvoker.java:220)
at org.testng.internal.TestInvoker$MethodInvocationAgent.invoke(TestInvoker.java:832)
at org.testng.internal.TestInvoker.invokeTestMethods(TestInvoker.java:147)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:146)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:128)
at java.base/java.util.ArrayList.forEach(Unknown Source)
at org.testng.TestRunner.privateRun(TestRunner.java:764)
at org.testng.TestRunner.run(TestRunner.java:585)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:384)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:378)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:337)
at org.testng.SuiteRunner.run(SuiteRunner.java:286)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:53)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:96)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1218)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1140)
at org.testng.TestNG.runSuites(TestNG.java:1069)
at org.testng.TestNG.run(TestNG.java:1037)
at org.testng.remote.AbstractRemoteTestNG.run(AbstractRemoteTestNG.java:115)
at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:251)
at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:77)
I am not sure why cucumber gives a NullPointerException
and testng one does not. using `e.printStackTrace()' I see that the driver is null.
I have looked at answers such as null-pointer-exception-when-trying-to-take-a-screenshot-with-selenium and exception-while-taking-screenshot but nothing helped.