Я пытаюсь запустить автоматические тесты параллельно через TestNGCucumberRunner, и моя проблема в том, что я создаю экземпляры своих PageObjects с помощью статического метода get из моего класса Manager, поскольку драйвер внутри него является статическим. Я уверен, что это проблема для параллельного выполнения. Как получить драйвер потокобезопасным способом?
Любая помощь приветствуется.
Редактировать: Мой текущий класс драйверов:
public class LocalDriverManager {
private static ThreadLocal<AppiumDriver> localDriver = new ThreadLocal<>();
public static AppiumDriver getDriver() {
return localDriver.get();
}
static void setDriver(AppiumDriver driver) {
localDriver.set(driver);
}
public static ThreadLocal<AppiumDriver> getLocalDriver() {
return localDriver;
}
}
Здесь я инициализирую драйвер в другом классе:
Вот как я инициализирую драйвер и устанавливаю ThreadLocal в другом классе:
if (capabilities.getPlatform().is(Platform.IOS)) {
driver = new IOSDriver<MobileElement>(new URL(urlStart + appiumServer.getPort() + "/wd/hub"),
capabilities);
} else {
driver = new AndroidDriver<MobileElement>(
new URL(urlStart + appiumServer.getPort() + "/wd/hub"),
capabilities);
}
LocalDriverManager.setDriver(driver);
Я устанавливаю переменную localDriver, когда устанавливаю драйвер в другом классе, и на
public BasePage(AppiumDriver driver, WebDriverWait wait) {
this.driver = driver;
this.wait = wait;
PageFactory.initElements(new AppiumFieldDecorator(driver, Duration.ofSeconds(10)), this);
}
Я получаю это исключение сейчас:
java.lang.IllegalArgumentException: Can not set io.appium.java_client.MobileElement field ba.woop.automation.pages.LandingPage.itsBanking to org.openqa.selenium.remote.RemoteWebElement$$EnhancerByCGLIB$$d27c0df4
at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
at java.base/jdk.internal.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:81)
at java.base/java.lang.reflect.Field.set(Field.java:780)
at org.openqa.selenium.support.PageFactory.proxyFields(PageFactory.java:117)
at org.openqa.selenium.support.PageFactory.initElements(PageFactory.java:105)
at ba.woop.automation.BasePage.<init>(BasePage.java:35)
at ba.woop.automation.pages.LandingPage.<init>(LandingPage.java:30)
at ba.klika.automation.steps.LoginCheckSteps.<init>(LoginCheckSteps.java:13)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
at org.picocontainer.injectors.AbstractInjector.newInstance(AbstractInjector.java:145)
at org.picocontainer.injectors.ConstructorInjector$1.run(ConstructorInjector.java:342)
at org.picocontainer.injectors.AbstractInjector$ThreadLocalCyclicDependencyGuard.observe(AbstractInjector.java:270)
at org.picocontainer.injectors.ConstructorInjector.getComponentInstance(ConstructorInjector.java:364)
at org.picocontainer.injectors.AbstractInjectionFactory$LifecycleAdapter.getComponentInstance(AbstractInjectionFactory.java:56)
at org.picocontainer.behaviors.AbstractBehavior.getComponentInstance(AbstractBehavior.java:64)
at org.picocontainer.behaviors.Stored.getComponentInstance(Stored.java:91)
at org.picocontainer.DefaultPicoContainer.getInstance(DefaultPicoContainer.java:699)
at org.picocontainer.DefaultPicoContainer.getComponent(DefaultPicoContainer.java:647)
at org.picocontainer.DefaultPicoContainer.getComponent(DefaultPicoContainer.java:678)
at io.cucumber.picocontainer.PicoFactory.getInstance(PicoFactory.java:42)
at cucumber.runtime.java.ObjectFactoryLoader$ObjectFactoryAdapter.getInstance(ObjectFactoryLoader.java:157)
at cucumber.runtime.java.JavaStepDefinition.execute(JavaStepDefinition.java:57)
at cucumber.runner.PickleStepDefinitionMatch.runStep(PickleStepDefinitionMatch.java:50)
at cucumber.runner.TestStep.executeStep(TestStep.java:65)
at cucumber.runner.TestStep.run(TestStep.java:50)
at cucumber.runner.PickleStepTestStep.run(PickleStepTestStep.java:43)
at cucumber.runner.TestCase.run(TestCase.java:46)
at cucumber.runner.Runner.runPickle(Runner.java:50)
at io.cucumber.testng.TestNGCucumberRunner.runScenario(TestNGCucumberRunner.java:79)
at ba.woop.automation.runners.LoginCheckRunner.runScenario(LoginCheckRunner.java:36)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:124)
at org.testng.internal.Invoker.invokeMethod(Invoker.java:583)
at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:719)
at org.testng.internal.TestMethodWithDataProviderMethodWorker.call(TestMethodWithDataProviderMethodWorker.java:71)
at org.testng.internal.TestMethodWithDataProviderMethodWorker.call(TestMethodWithDataProviderMethodWorker.java:14)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
at ?.the user clicks on LOGIN button on LANDING PAGE(file:src/test/resources/features/loginCheck.feature:3)