Падают тесты в TestNG с использованием нескольких браузеров одновременно, принято решение попробовать обернуть в ThreadLocal. Помогите разобраться с чем его едят и как правильно использовать RemoteWebDriver get Driver() {return Driver.get()}.
И так, мой базовый класс:
public class RemoteTestBase {
private static final String SAUCE_ACCESS_KEY = System.getenv("SAUCE_ACCESS_KEY");
private static final String SAUCE_USERNAME = System.getenv("SAUCE_USERNAME");
public ThreadLocal<RemoteWebDriver> driver = new ThreadLocal<>();
@BeforeMethod
@DataProvider(name = "browsers", parallel = true)
public static Object[][] sauceBrowserDataProvider(Method testMethod) throws JSONException {
String browsersJSONArrayString = System.getenv("SAUCE_ONDEMAND_BROWSERS");
JSONArray browsersJSONArrayObj = new JSONArray(browsersJSONArrayString);
Object[][] browserObjArray = new Object[browsersJSONArrayObj.length()][3];
for (int i=0; i < browsersJSONArrayObj.length(); i++) {
JSONObject browserObj = (JSONObject)browsersJSONArrayObj.getJSONObject(i);
browserObjArray[i] = new Object[]{browserObj.getString("browser"),
browserObj.getString("browser-version"), browserObj.getString("os")}; }
return browserObjArray; }
void createRemoteDriver(String browser, String version, String os, String methodName)
throws Exception {
DesiredCapabilities capabilities = new DesiredCapabilities();
Class<? extends RemoteTestBase> SLclass = this.getClass();
capabilities.setCapability("browserName", browser);
if (version != null) {
capabilities.setCapability("browser-version", version);
}
capabilities.setCapability("platform", os);
capabilities.setCapability("name", SLclass.getSimpleName());
capabilities.setCapability("tunnelIdentifier", "***");
URL url = new URL("http://" + SAUCE_USERNAME + ":" + SAUCE_ACCESS_KEY+
"@ondemand.saucelabs.com:80/wd/hub"))
RemoteWebDriver rwd = new RemoteWebDriver(url, capabilities);
driver.set(rwd);
randomuser = new RandomDataSelect();
configRead = new ConfigFileReader();
propertyRead = new PropertyLoader();
baseUrl = propertyRead.getProperty("site.url");
getURL();
}
protected RemoteWebDriver getDriver(){
return driver.get(); }
private void getURL() {
getDriver().get(baseURL);}
@AfterMethod(description = "Throw the test execution results into saucelabs")
public void tearDown(ITestResult result) {
String texts = "auce:job-result=" + (result.isSuccess() ? "passed" : "failed"));
getDriver().quit(); }
В каждом пейдж классе инициализирован драйвер таким образом:
public class LoginObjects {
private Webdriver driver;
@FindBy(how=How.ID, using="aaa")
public WebElement ElementOne;
//какой-нибудь метод, после он передастся в основной тест:
public void LoginAs() {
WebDriverWait wait = new WebDriverWait(driver, 40)
ElementOne.click()}
// прописан конструктор:
public LoginObjects(WebDriver driver){
this.driver = driver;
PageFactory.initElements(driver, this)}
Каждый такой Пейдж с объектами прописан в классе Аппликейшн:
public class Application {
private WebDriver driver;
public Application(WebDriver driver)
{ this.driver=driver; }
public LoginObjects loginobjects() {
return new LoginObjects(driver) }
Не исключаю, что данный подход не самый целесообразный, любые советы как не использовать инициализацию браузера в каждом классе будут полезны, но вопрос в другом.
Каким образом вызывать/инициализировать WebDriver driver, когда в базовом классе используется RemoteWebDriver get Driver() ?? Естественно, если оставить все как есть то NullPointerException не заставить себя ждать.
Напоследок образец самого тестового класса, расширяющего базовый:
public class Login extends RemoteTestBase {
@Test (dataProvider = "browsers")
public void LoginTest(String browser, String version, String os, Method method) throws Exception {
this.createRemoteDriver(browser, version, os, method.getName());
Application app = new Application (driver);
app.loginobjects().login_as(); }
Проект построен на TestNG.
Буду безмерно благодарна за помощь