Я запускаю параллельные тесты с использованием сетки selenium (selenium-server-standalone-2.47.1.jar) с TestNg, запускаемой ant, и с использованием TestListenerAdapter. Скриншоты делаются в методе onTestFailure слушателя. Проблема в том, что слушатель, кажется, не понимает, какой драйвер он должен использовать, и иногда делает снимок экрана неправильного окна браузера или вообще не работает, если драйвер, который, по его мнению, должен использовать, уже завершил работу.
Когда запускаются тесты, методы TestNg @BeforeTest и TestListenerAdapter 'onTestStart' выполняются в одном потоке, но когда тест завершается неудачно, метод onTestFailure TestListenerAdapter запускается в отдельном потоке. Кажется, что нити каким-то образом пересекаются / разделяются, но я не могу понять, почему.
Вот какой-то скелетный код, любая помощь очень ценится.
Базовый тестовый класс:
public class baseClassTests{
protected AutomationUtils au;
protected DriverUtils du;
@BeforeTest(alwaysRun = true)
@Parameters({ "selenium.OS", "selenium.browser" })
public void beforeTest(String OS, String browser) {
//these call simple private methods to know where to set up the driver
String port = getPort(OS, browser);
String host = getHost(OS);
//make a driver utility object here, this makes a driver
du = new DriverUtils(browser, host, port);
//pass this driver utility object to another class of utilities
//this 'AutomationUtils' class gets a RemoteWebDriver ('driver') by calling driver=du.getDriver();
//the 'AutomationUtils' class is then the one that does all of the 'driver.findBy...' etc
au = new AutomationUtils(du);
}
@BeforeMethod(alwaysRun = true)
public void beforeMethod(Method m, ITestResult tr) {
du.deleteCookies();
testNgTestName = m.getName();
print("Method: "+testNgTestName + " Thread: "+Thread.currentThread().hashCode());
//set the attribute of the ITestResult object so we can use the same object in the listener
tr.setAttribute("du", du);
tr.setAttribute("au", au);
}
}
Класс слушателя
public class AmSimpleTestListener extends TestListenerAdapter {
private DriverUtils driveU;
private AutomationUtils AutoU;
private RemoteWebDriver driver;
private RemoteWebDriver augmentedDriver;
private String methodName;
private String browser;
private String browserVersion;
String testClass;
@Override
public void onTestStart(ITestResult tr) {
//pick up the correct driver utility object from the test class/method we are in
driveU = (DriverUtils) tr.getAttribute("du");
AutoU = (AutomationUtils) tr.getAttribute("au");
driver = du.getDriver();
augmentedDriver = (RemoteWebDriver) new Augmenter().augment(driver);
methodName = tr.getName();
testClass=tr.getTestClass(); //sort of, I actually parse it up a bit
browser = driveU.getBrowser();
browserVersion = driveU.getBrowserVersion();
print("Method: "+methodName + " Thread: "+Thread.currentThread().hashCode());
}
@Override
public void onTestFailure(ITestResult tr) {
print("Method: "+tr.getName() + " Thread: "+Thread.currentThread().hashCode());
try{
writeScreenshotFile();
}
catch (Exception e){
Out.error("Unable to take screen shot");
e.printStackTrace();
}
}
private String writeScreenshotFile() {
if (driver != null && driver.getSessionId() != null) {
File scrShot = ((TakesScreenshot) augmentedDriver).getScreenshotAs(OutputType.FILE);
File localPathToScreenShot = new File("/path/to/base/directory/"+testClass+"/"+methodName+".png");
try {
FileUtils.copyFile(scrShot, localPathToScreenShot);
} catch (Exception e) {
Out.error("Couldn't write screenshot to file");
}
return localPathToScreenShot.getAbsolutePath();
}
return "Could not get path.";
}
}
Класс DriverUtils создает / поставляет драйвер
public class DriverUtils {
private RemoteWebDriver driver;
private int timeout;
private String browserVersion;
private String browser
private DesiredCapabilities caps;
public DriverUtils(String browser, String host, String port) {
String hostUrl = "http://" + host + ":" + port + "/wd/hub";
this.browser=browser;
//do some stuff here to set capabilties
driver = new RemoteWebDriver(new URL(hostUrl), caps);
browserVersion = driver.getCapabilities().getVersion();
}
public RemoteWebDriver getDriver() {
return driver;
}
public AmBrowser getBrowser() {
return browser;
}
public String getBrowserVersion() {
return browserVersion;
}
public void quitDriver() {
driver.quit();
}
public void deleteCookies(){
driver.manage().deleteAllCookies();
}
}
public class AutomationUtils extends BaseClassUtils {
public AutomationUtils(DriverUtils driverUtils) {
//pass it up to the base class utils (this is different than base class tests, above)
//do this so the driver can be accessed by other utility classes as well
super(driverUtils);
}
//All sorts of methods here to find elements, login, blah blah everything that is done with a driver object
}
public class BaseClassUtils { //this is a different class than BaseClassTests
//make the driver a protected object so all utility classes can access as nec.
protected final RemoteWebDriver driver;
public BaseClassUtils(DriverUtils driverUtils) {
driver = driverUtils.getDriver();
}
}
Тесты запускаются через ant.
<suite name="Dev2 for debugging" parallel="tests" thread-count="10">-- tests here </suite>