【问题标题】:TestNG Appium Parallel execution not workingTestNG Appium 并行执行不起作用
【发布时间】:2020-03-01 00:42:57
【问题描述】:

我正在尝试通过 TestNGCucumberRunner 并行运行自动化测试,我的问题是我使用 Manager 类中的静态 get 方法实例化了我的 PageObjects,因为其中的驱动程序是静态的。我很确定这是并行执行的问题。如何以线程安全的方式检索驱动程序?

感谢任何帮助。

编辑: 我当前的驱动程序类:

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)

【问题讨论】:

  • 创建一个单独的驱动管理器类并将驱动对象声明为 ThreadLocal。您将不得不使用 setter/getter 方法来存储您的线程驱动程序并在需要时检索它。
  • @Sureshmani 我尝试了这种方法,但它对我不起作用。还是应该是一个单独的类,只包含驱动程序?

标签: cucumber testng appium


【解决方案1】:

您需要创建特定的类来存储每个线程的“驱动程序”。

public class ThreadLocalDriver {

    private static ThreadLocal<AppiumDriver> tlDriver = new ThreadLocal<>();

    public static ThreadLocal<AppiumDriver> getTlDriver() {
        return tlDriver;
    }

    public static void setTLDriver(AppiumDriver driver) {
            tlDriver.set(driver);
    }
}

一旦您需要获取驱动程序,只需调用静态方法ThreadLocalDriver.getTlDriver().get();

【讨论】:

  • 我现在正是这样做的,但是在我的 StepDefinition 文件中第一次实例化页面对象时我得到了`java.lang.IllegalArgumentException`
  • 哦,我明白了。您需要致电 ThreadLocalDriver.getTlDriver().get(); 而不仅仅是 ThreadLocalDriver.getTlDriver();
  • 这不是问题,我在问题中发布了我的驱动程序类。
  • 那么您可能在驱动程序中使用了类型,例如AppiumDriver&lt;MobileElement&gt;。尝试删除泛型类型并再次运行它。
  • 我已经改变了这个,但得到了同样的错误。我添加了导致上述异常的 coden-p。看来 initElements 方法这个方法有问题
猜你喜欢
  • 1970-01-01
  • 2019-12-13
  • 1970-01-01
  • 2023-03-31
  • 2016-10-22
  • 2017-07-22
  • 1970-01-01
  • 2020-08-08
  • 2020-03-01
相关资源
最近更新 更多