I have a selenium project that is running parallel tests via testng. When the test fails I have a listener class that captures the screenshot. The class is as follows
public class ScreenshotOnFailure extends TestListenerAdapter {
@Override
public void onTestFailure(ITestResult tr) {
WebDriver driver = SeleniumSetup.driverrunning;
boolean hasQuit = driver.toString().contains("(null)");
if(!hasQuit){
System.out.println(driver);
File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
DateFormat dateFormat = new SimpleDateFormat("dd_MMM_yyyy__hh_mm_ssaa");
Date date = new Date();
String NewFileNamePath = null;
File directory = new File(".");
String methodName = tr.getMethod().getMethodName();
try {
NewFileNamePath =directory.getCanonicalPath() + "\\target\\surefire-reports\\html\\Screenshots\\"+methodName+"_"+ dateFormat.format(date) +"Listener.png";
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
FileUtils.copyFile(scrFile, new File(NewFileNamePath));
} catch (IOException e) {
e.printStackTrace();
}
String reportFilePath = ".\\Screenshots\\"+methodName+"_"+ dateFormat.format(date) +".png";
System.setProperty("org.uncommons.reportng.escape-output", "false");
Reporter.log("<a href=" + reportFilePath + ">Click to open screenshot</a><img src=" + reportFilePath + " height='350' width='700'>");
}
}}
In my tests I have a AfterMethod that cleans up the test
@AfterMethod(alwaysRun = true)
public void tearDown() throws Exception
{
driver.quit();
}
If test are run one by one then the correct browser screenshot is captured however if I run parrallel testsit captures the wrong test browser. I think the problem may be one of the following
- The after method has already quit the browser(This is a case sometimes thus why I had to add the hasQuit boolean)
- The listene is referencing the wrong driver object. I believe this is the problem but I'm not sure how to make sure it references the correct driver.
I have a workaround that work which pretty much invloves creating a static screen capture object and then adding that to the AfterMethod, However this is less than ideal as I would like to use a listener.