Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Non Static driver and screenshot listener in TestNG

I have a testcase that will invoke the driver as a non static variable. I also have added screenshot listener in my test case. When the test case fails The control is automatically sent to the screenshot listener... however since my driver is a NON-STATIC variable it could not be accessed in the screenshot listener. So I get nullpointer exception.

Is there a way to globally access the non-static driver in the screenshot listener?

My test case :

@Test
public void testCase() {
     //non-static driver is initialized
}

My screenshot listener :

public class ScreenshotListener extends TestListenerAdapter
{
    @Override
    public void onTestFailure(ITestResult testResult) {
        //driver needs to be accessed here
    }
}
like image 587
Damien-Amen Avatar asked Jul 12 '13 00:07

Damien-Amen


People also ask

How many types of listeners are there in TestNG?

In the parent class, we use two TestNG listeners. onTestSuccess() method that will run when the test case is successfully executed. onTestFailure() method that will run when the test case fails.

How do I take a screenshot using listeners?

Here are steps to capture screenshot in Selenium using TestNG Listener: Create a class. Implement TestNG 'ITestListener'. Call the method 'onTestFailure'.

How many types of listeners are there in Selenium?

There are two types of Selenium Listeners: WebDriver Listeners. TestNG Listeners.


2 Answers

I was going to go for the solution provided by Robbie but wanted to avoid tying up my base class. As i was using to Guice to inject my WebDriver provider i opted to pass the instance through a TestNG attribute by hooking it up once in a setup test class like so:

public class Setup {
    @Inject WebDriver driver;

    @BeforeSuite
    public void onStart(ITestContext testContext) {
        testContext.setAttribute("WebDriver", this.driver);
    }
}

Then in my listener i simply pull it out:

@Override
public void onTestFailure(ITestResult result) {

    Object webDriverAttribute = 
        result.getTestContext().getAttribute("WebDriver");
    // test, cast, and use...

Was hoping for a better way that did not require casting but yet to find one.

like image 61
JackC Avatar answered Oct 14 '22 21:10

JackC


YOu do not have to pass the driver around or call on testfailure within the test (infact this defeats the point of test listeners);

The following will achieve screenshots in listeners without passing the driver around;

  1. All test classes must extend a simple base test class;

    public asbtract baseTestCase() {
    
        private WebDriver driver;
    
        public WebDriver getDriver() {
                return driver;
    }
    
        @BeforeMethod
        public void createDriver() {
                Webdriver driver=XXXXDriver();
        }
    
        @AfterMethod
            public void tearDownDriver() {
            if (driver != null)
            {
                    try
                    {
                        driver.quit();
                    }
                    catch (WebDriverException e) {
                        System.out.println("***** CAUGHT EXCEPTION IN DRIVER TEARDOWN *****");
                        System.out.println(e);
                    }
    
            }
        }
    
  2. In your listener, you need to access the base class;

public class ScreenshotListener extends TestListenerAdapter {

@Override
public void onTestFailure(ITestResult result)
{
        Object currentClass = result.getInstance();
        WebDriver webDriver = ((BaseTest) currentClass).getDriver();

        if (webDriver != null)
        {

           File f = ((TakesScreenshot) webDriver).getScreenshotAs(OutputType.FILE);

           //etc.
        }
}

Your test is now unaware that a screenshgot is even being captured and can be controlled by the adding of the listener.

like image 25
Robbie Wareham Avatar answered Oct 14 '22 22:10

Robbie Wareham