4

I am working with ExtentReports and ItestListener for my testng-selenium-java project, My listener takes screenshot for the failes test case for ExtentReports but the problem is that I have multiple classes in my testng.XML and I run them in one go, one after the other doing different things and having own drivers.

In the failed case the code for Ilistener is -

public void onTestFailure(ITestResult iTestResult) 
{
    System.out.println("I am in onTestFailure method " +  
    getTestMethodName(iTestResult) + " failed");

    //Get driver from BaseTest and assign to local webdriver variable.
    Object testClass = iTestResult.getInstance();
    WebDriver webDriver = ((BaseTest) testClass).getDriver();


    //Take base64Screenshot screenshot.
    String base64Screenshot = "data:image/png;base64,"+((TakesScreenshot)webDriver).
            getScreenshotAs(OutputType.BASE64);

    //Extentreports log and screenshot operations for failed tests.
    ExtentTestManager.getTest().log(LogStatus.FAIL,"Test Failed",
            ExtentTestManager.getTest().addBase64ScreenShot(base64Screenshot));
}

How to make sure that the driver of the failed test case's class is taken whenever a test case is failed, because in the above code only one class's driver is given all the time and not the current class's.

Ahmed Ashour
  • 5,179
  • 10
  • 35
  • 56
kritika agarwal
  • 505
  • 1
  • 6
  • 11
  • At the first glance, there are no obvious issues here. Maybe you could also include some fragment of BaseTest class, containing `driver` field definition and initialization, as this would help in identifying any problems. – Edvins May 15 '18 at 14:24

4 Answers4

8

it is simple you can set the attribute in your test class and then call this attribute in you listener class

For example

testClass.java

@BeforeClass
public void setDriver(ITestContext context){
  Webdriver driver = new FirefoxDriver();
  context.setAttribute("WebDriver", driver);
}
@Test
public void t1(){
   // your code
}

Listener.java

WebDriver driver = null;
@Override
public void onTestFailure(ITestResult result) {
    ITestContext context = result.getTestContext();
    driver = (WebDriver) context.getAttribute("WebDriver");
    // your code
}

Here you need to make a note that in your test class you need to set the driver attribute and then call this attribute in that listener once. your driver in test class and listener class will be the same

Suhail Ahmed
  • 504
  • 1
  • 9
  • 19
1

I got a solution to it, for a non static driver, when you have multiple classes having own driver and running own features one can set a base class with drivers initialization and a getdriver function which will get the driver from the base class and extend the class from other classes-

class BaseClass
{
WebDriver driver;

public WebDriver getDriver()
{
system.setproperty()
driver=new ChromeDriver();

return driver;
}

Class Test1 extends BaseClass
{
BaseClass bc=new BaseClass()
@BeforTest
public void setup()
{
driver=bc.getDriver()
//rest processing
}
kritika agarwal
  • 505
  • 1
  • 6
  • 11
0

Another way can be (above also worked for me btw -Suhail's answer)...

public class WhereWebDriverIsDefined {
  public WebDriver webDriver;
  //initialize driver in @BeforeTest or @BeforeClass method
  @BeforeTest
  public void init() {
    System.setProperty("webdriver.chrome.driver","D:\\WebDriverLocation\\chromedriver.exe");
    driver= new ChromeDriver();
}  

From Listener class try to access the webDriver (can be called on other listener methods too)

public void onTestFailure(ITestResult result) {
    WebDriver driver= null;
    try {
        driver= (WebDriver) result.getTestClass().getRealClass().getDeclaredField("driver").get(result.getInstance());
    } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) {
        e.printStackTrace();
    }
  }
CodeWorld
  • 2,017
  • 1
  • 11
  • 21
0

I had the same issue. I remember the solution from one of my training courses. (WebDriver)result.getTestClass().getRealClass().getDeclaredField("driver").get(result.getInstance()); you can access the fields present in class that caused the listener to trigger.

rez shahr
  • 49
  • 3