0

I am using Selenium WebDriver and am looking to have the driver take a screenshot upon test failure. For this purpose, I am using the following code for the onTestFailure() method of my TestNG listener class:

@Override
public void onTestFailure(ITestResult arg0) {
    String fileName = String.format("Screenshot-%s.jpg", Calendar.getInstance().getTimeInMillis());
    driver = (WebDriver)arg0.getTestContext().getAttribute("WebDriver");
    TakesScreenshot ts = (TakesScreenshot)driver;
    File srcFile = ts.getScreenshotAs(OutputType.FILE);
    File destFile = new File("./screenshots/" + fileName); 
    try{ 
        FileUtils.copyFile(srcFile, destFile);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

However, I am getting a NullPointerException that the driver is null. I know I can get around this by making the driver field in my test class static, but is there any other way that can avoid this?

I looked through similar questions on Stack Exchange but was unable to find one that worked for me.

1
  • How and where do you put webdriver object to test context?
    – Alexey R.
    Commented Oct 31, 2018 at 17:50

1 Answer 1

2

See my example below. This shows how to take screenshots with test listeners, however you can do the same just in your @AfterTest method. Nevertheless:

This is the test class:

@Listeners({MyTestListener.class})

public class MiscTests {

    WebDriver driver;

    @BeforeTest
    public void setUp(ITestContext context){
        System.out.println("Starting set up..");
        System.setProperty("webdriver.chrome.driver", "E:/Dev/WebDrivers/chromedriver.exe");
        driver = new ChromeDriver();
        driver.get("https://www.w3schools.com/cssref/pr_background-color.asp");
        context.setAttribute("webDriver", driver);
        System.out.println("Webdriver created and added to context");
    }

    @Test
    public void testScreenshotsOnFail(ITestContext context){
        System.out.println("Starting test that hast to fail..");
        Assert.assertEquals(1, driver.findElements(By.xpath("//blah")).size());
    }

    @AfterTest
    public void tearDown(){
        if(driver != null){
            driver.quit();
            System.out.println("Driver was instantiated. Quitting..");
        }else{
            System.out.println("Driver was null so nothing to do");
        }
    }

}

I have added some extensive logging here so that you can track execution of different parts of the test. The test is intentionally developed to fail. Also pay attention that we're adding driver object to test context. Without adding anything you won't be able to get anything.

This is the listener class:

public class MyTestListener extends TestListenerAdapter {
    @Override
    public void onTestFailure(ITestResult arg0){
        System.out.println("Failure detected...");
        String fileName = String.format("Screenshot-%s.jpg", Calendar.getInstance().getTimeInMillis());
        WebDriver driver = (WebDriver)arg0.getTestContext().getAttribute("webDriver");
        TakesScreenshot ts = (TakesScreenshot)driver;
        File srcFile = ts.getScreenshotAs(OutputType.FILE);
        File destFile = new File("./screenshots/" + fileName);
        try{
            FileUtils.copyFile(srcFile, destFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("Screenshot taken");
    }
}

I slightly reworked your code and added track log records as well. The output shows then:

Starting set up..
Starting ChromeDriver 2.38.552522 (437e6fbedfa8762dec75e2c5b3ddb86763dc9dcb) on port 37504
Only local connections are allowed.
окт 31, 2018 10:30:42 PM org.openqa.selenium.remote.ProtocolHandshake createSession
INFO: Detected dialect: OSS
Webdriver created and added to context
Starting test that hast to fail..
Failure detected...
Screenshot taken

java.lang.AssertionError: expected [0] but found [1]
Expected :0
Actual   :1
 <Click to see difference>


    at org.testng.Assert.fail(Assert.java:96)
    at org.testng.Assert.failNotEquals(Assert.java:776)
    at org.testng.Assert.assertEqualsImpl(Assert.java:137)
    at org.testng.Assert.assertEquals(Assert.java:118)
    at org.testng.Assert.assertEquals(Assert.java:652)
    at org.testng.Assert.assertEquals(Assert.java:662)
    at TestAppPopUp.testScreenshotsOnFail(TestAppPopUp.java:30)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:124)
    at org.testng.internal.Invoker.invokeMethod(Invoker.java:583)
    at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:719)
    at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:989)
    at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:125)
    at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:109)
    at org.testng.TestRunner.privateRun(TestRunner.java:648)
    at org.testng.TestRunner.run(TestRunner.java:505)
    at org.testng.SuiteRunner.runTest(SuiteRunner.java:455)
    at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:450)
    at org.testng.SuiteRunner.privateRun(SuiteRunner.java:415)
    at org.testng.SuiteRunner.run(SuiteRunner.java:364)
    at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
    at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:84)
    at org.testng.TestNG.runSuitesSequentially(TestNG.java:1208)
    at org.testng.TestNG.runSuitesLocally(TestNG.java:1137)
    at org.testng.TestNG.runSuites(TestNG.java:1049)
    at org.testng.TestNG.run(TestNG.java:1017)
    at org.testng.IDEARemoteTestNG.run(IDEARemoteTestNG.java:72)
    at org.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:123)

Driver was instantiated. Quitting..

===============================================
Default Suite
Total tests run: 1, Failures: 1, Skips: 0
===============================================


Process finished with exit code 0
1
  • Thank you very much - I was able to resolve the issue. The problem was that I did not properly set the driver attribute to the test context.
    – A. K
    Commented Nov 2, 2018 at 13:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.