未应用 Selenium-Jupiter 通用网络驱动程序设置

Selenium-Jupiter generic webdriver settings not applied

我想在我的 Spring 启动项目中使用 Selenium-Jupiter,但我的要求是在运行时切换 WebDriver 实现 - 基于执行环境 - 使用一个公共基础 class测试。

我已经检查过 this post and ,但我无法让它工作。

堆栈跟踪:

  2020-09-17 23:17:47.196  INFO 14092 --- [    Test worker] d[....path....].SignupPageTest  : Started SignupPageTest in 26.133 seconds (JVM running for 29.179)
    2020-09-17 23:17:47.498  WARN 14092 --- [    Test worker] i.g.bonigarcia.seljup.SeleniumExtension  : Driver handler for context id [engine:junit-jupiter]/[class:de,[....path....].SignupPageTest]/[method:verifyLogInPage(org.openqa.selenium.WebDriver)] not found

    Failed to resolve parameter [org.openqa.selenium.WebDriver genDriver] in method [public void de.[....path....].SignupPageTest.verifyLogInPage(org.openqa.selenium.WebDriver) throws java.lang.Exception]: org/glassfish/hk2/api/MultiException
    org.junit.jupiter.api.extension.ParameterResolutionException: Failed to resolve parameter [org.openqa.selenium.WebDriver genDriver] in method [public void de.[....path....].SignupPageTest.verifyLogInPage(org.openqa.selenium.WebDriver) throws java.lang.Exception]: org/glassfish/hk2/api/MultiException
        at org.junit.jupiter.engine.execution.ExecutableInvoker.resolveParameter(ExecutableInvoker.java:239)
        at org.junit.jupiter.engine.execution.ExecutableInvoker.resolveParameters(ExecutableInvoker.java:183)
        at org.junit.jupiter.engine.execution.ExecutableInvoker.resolveParameters(ExecutableInvoker.java:144)
        at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:96)
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod(TestMethodTestDescriptor.java:212)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:208)
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:137)
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:71)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:135)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:125)
        at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:123)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
        at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
        at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:139)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:125)
        at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:123)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
        at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
        at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:139)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:125)
        at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:123)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
        at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
        at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
        at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
        at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:248)
        at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute(DefaultLauncher.java:211)
        at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:226)
        at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:199)
        at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:132)
        at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:99)
        at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access[=10=]0(JUnitPlatformTestClassProcessor.java:79)
        at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:75)
        at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61)
        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:564)
        at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
        at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
        at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
        at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
        at com.sun.proxy.$Proxy5.stop(Unknown Source)
        at org.gradle.api.internal.tasks.testing.worker.TestWorker.stop(TestWorker.java:133)
        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:564)
        at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
        at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
        at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:182)
        at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:164)
        at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:414)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
        at org.gradle.internal.concurrent.ManagedExecutorImpl.run(ManagedExecutorImpl.java:48)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
        at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
        at java.base/java.lang.Thread.run(Thread.java:832)
    Caused by: java.lang.NoClassDefFoundError: org/glassfish/hk2/api/MultiException
        at io.github.bonigarcia.seljup.DockerService.<init>(DockerService.java:79)
        at io.github.bonigarcia.seljup.SeleniumExtension.initHandlerForDocker(SeleniumExtension.java:381)
        at io.github.bonigarcia.seljup.SeleniumExtension.getDriverHandler(SeleniumExtension.java:242)
        at io.github.bonigarcia.seljup.SeleniumExtension.resolveParameter(SeleniumExtension.java:220)
        at org.junit.jupiter.engine.execution.ExecutableInvoker.resolveParameter(ExecutableInvoker.java:216)
        ... 73 more
    Caused by: java.lang.ClassNotFoundException: org.glassfish.hk2.api.MultiException
        at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:602)
        at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
        ... 78 more
    
    de.[....path....].SignupPageTest > verifyLogInPage(WebDriver) FAILED
        org.junit.jupiter.api.extension.ParameterResolutionException at ExecutableInvoker.java:239
            Caused by: java.lang.NoClassDefFoundError at DockerService.java:79
                Caused by: java.lang.ClassNotFoundException at BuiltinClassLoader.java:602

提前使用 chrome-driver 一切正常,但不适用于通用 webdriver。

我使用 Java14 并为名为“endToEndTest”的 selenium 测试创建了一个额外的源集
这是 gradle.build:

中的所有相关内容
sourceCompatibility = 14

sourceSets {
    endToEndTest {
        java.srcDir('src/end-to-end-test/java')
        resources.srcDir file('src/end-to-end-tests/resources')
        compileClasspath += sourceSets.main.output + configurations.testRuntime
        runtimeClasspath += output + compileClasspath
    }
}

configurations {
    endToEndTestImplementation.extendsFrom testImplementation
    endToEndTestRuntimeOnly.extendsFrom testRuntimeOnly
}

task endToEndTest(type: Test) {
    testClassesDirs = sourceSets.endToEndTest.output.classesDirs
    classpath = sourceSets.endToEndTest.runtimeClasspath
    useJUnitPlatform ()
}

endToEndTestImplementation('io.github.bonigarcia:selenium-jupiter:3.3.5')

我有一个基础 class,每个其他测试 class 都应该从该基础扩展。它负责启动网络环境等

基础class

@ExtendWith({SpringExtension.class})
@SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class SeleniumBaseTestEnvironment {

  @RegisterExtension
  static SeleniumExtension seleniumJupiter = new SeleniumExtension();

  @LocalServerPort
  protected int serverPort;

  @BeforeAll
  public static void beforeAll() {
    //both seems to have no impact
    seleniumJupiter.getConfig().setDefaultBrowser("chrome");
    seleniumJupiter.addBrowsers(BrowserBuilder.chrome().build());
  }

  protected String getUrl(String address) {
    return "http://localhost:" + serverPort + address;
  }
}

测试class 如果我将 WebDriver 替换为 ChromeDriver,它就可以正常工作。但是我需要通用驱动程序。

public class SignupPageTest extends SeleniumBaseTestEnvironment {

  @Test
  public void verifyLogInPage(WebDriver genDriver) throws Exception {
    genDriver.get(getUrl("/"));
    List<WebElement> cardTitleList = genDriver.findElements(By.className("card-title"));
    List<WebElement> navbar = genDriver.findElements(By.className("navbar-toggler collapsed"));
    assertEquals(cardTitleList.get(0).getText(), "Login");
    assertTrue(navbar.isEmpty());

  }
}

似乎我关于默认浏览器的设置没有应用。其他设置(如屏幕截图设置)工作正常。

根据我的研究,将浏览器添加到 Selenium Extension 仅适用于 Selenium Jupiter 中的测试模板功能。

所以使用测试模板下面的代码应该可以工作:

    @ExtendWith({SpringExtension.class})
    @SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
    public class SeleniumBaseTestEnvironment {
    
      @RegisterExtension
      static SeleniumExtension seleniumJupiter = new SeleniumExtension();
    
      @LocalServerPort
      protected int serverPort;
    
      @BeforeAll
      public static void beforeAll() {
        String browsersList = System.getProperty("prop.browsers.list");
            List<String> browsers = Arrays.asList(browsersList.split(","));
        
        if (browsers.contains("chrome")) {
        seleniumJupiter.addBrowsers(BrowserBuilder.chrome().build()); 
        }
        if (browsers.contains("firefox")) {
            seleniumJupiter.addBrowsers(BrowserBuilder.firefox().build());
        }
        //----// All browsers you need
    
      }
    
      protected String getUrl(String address) {
        return "http://localhost:" + serverPort + address;
      }


public class SignupPageTest extends SeleniumBaseTestEnvironment {

    @TestTemplate
    public void verifyLogInPage(WebDriver genDriver) throws Exception {
        genDriver.get(getUrl("/"));
        List<WebElement> cardTitleList = genDriver.findElements(By.className("card-title"));
        List<WebElement> navbar = genDriver.findElements(By.className("navbar-toggler collapsed"));
        assertEquals(cardTitleList.get(0).getText(), "Login");
        assertTrue(navbar.isEmpty());

    }
}

请注意:

  1. 在我的示例中,我使用 VM 选项 -Dprop.browsers.list=chrome,firefox 以便为测试提供多个浏览器。
  2. 应为 SeleniumBaseTestEnvironment 的所有子 class 的每个方法放置注释 @TestTemplate。(您可以创建自己的 class 级别注释来解决它)。
  3. 为了切换 Webdriver 实现,您可以为每个环境设置一个 spring 配置,以提供适当的驱动程序列表。