在 docker 中分发黄瓜 junit 5 测试

distributing cucmber junit5 tests in docker

我有黄瓜项目 运行正在 Azure 构建和发布管道上。

我已经安装了 docker 和 docker-compose,我可以使用 docker-seleniumdocker-compose

打开容器和网格

我想分发黄瓜测试,有点像 as explained here . But in that link , it is explained using testng and I am using junit5 with cucumber . How would I achieve that , specially the below part from the link , in conjunction with what we know about cucumber parallelism in junit5?

@Parameters({"Port"})
@BeforeClass
public void initiateDriver(String Port) throws MalformedURLException {
            if(Port.equalsIgnoreCase("9001"))
    {
        driver = new RemoteWebDriver(new URL("http:localhost:4444/wd/hub"), DesiredCapabilities.chrome());
        driver.manage().window().maximize();
    }
    else if(Port.equalsIgnoreCase("9002")){
        driver = new RemoteWebDriver(new URL("http:localhost:4444/wd/hub"), DesiredCapabilities.firefox());
        driver.manage().window().maximize();
    }
}

据我了解,如果我在 junit-platform.properties 中提到 cucumber.execution.parallel.enabled=true ,每个功能文件都会 运行 并行,我如何提到 port 以实现以下

  1. 运行 一个容器中的每个特征
  2. 有没有办法将不同功能文件的每个场景分布在单独的容器中?

通常您会让 CI 运行 。这个测试矩阵已经可以并行 运行 个不同的作业。 矩阵中的每个作业都可以执行所有测试或一部分测试。您使用标签来包含或排除对某些作业配置的某些测试。这确保浏览器和 OS 特定问题立即显现。

这也稍微简化了问题。当您不启动具有不同浏览器类型的 Selenium Grid 时,您不必找到一种巧妙的方法将每个测试连接到正确的浏览器。

相反,您每项工作只需启动一个具有一种浏览器类型的 Selenium Grid。网格启动后,每个作业都可以 运行 通过使用多个远程网络驱动程序并行测试。 那么您所要做的就是确保您的测试不会尝试使用比网格可用更多的浏览器。这可以通过设置一些配置参数来完成:

cucumber.execution.parallel.enabled=true
cucumber.execution.parallel.config.strategy=fixed
cucumber.execution.parallel.config.fixed.parallelism=4 

您必须将这些 configuration parameters 用于您的测试执行。一种方法是使用 maven 配置文件,但还有许多其他方法可以做到这一点:

        <profile>
            <id>parallelism</id>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-failsafe-plugin</artifactId>
                        <configuration>
                            <properties>
                                <configurationParameters>
                                cucumber.execution.parallel.enabled=true
                                cucumber.execution.parallel.config.strategy=fixed
                                cucumber.execution.parallel.config.fixed.parallelism={env.CONCURRENT_TESTS}
                                </configurationParameters>
                            </properties>
                        </configuration>
                    </plugin>
                </plugins>
            </build>
        </profile>

你可以像这样把它绑在一起:

test:
  stage: test
  script:
    - ./start-selenium-grid $BROWSER $CONCURRENT_TESTS
    - mvn test -Pparallelism
  parallel:
    matrix:
      - OS: Windows
        OS_VERSION: 10
        BROWSER: [Chrome, Firefox, Edge]
        CONCURRENT_TESTS: 4
      - OS: OS X
        OS_VERSION: Big Sur
        BROWSER: [Chrome, Firefox, Edge, Safari]
        CONCURRENT_TESTS: 2

综上所述。首先 运行 为不同的浏览器并行构建作业。然后在每个作业中,运行 对多个网络驱动程序进行并行测试。

我找不到在场景级别并行化 junit5 测试的任何解决方案,所以我使用 testNGcourgette-jvm in conjunction with cucumber-guice。它开箱即用,运行 场景级别的并行测试

只需在黄瓜中包含类似的 运行ner class。我的测试进一步使用 RemoteWebdriver 在 selenium 网格上打开多个实例。确保网格已启动并且 运行ning 并且节点已注册到网格。

import courgette.api.CourgetteOptions;
import courgette.api.CourgetteRunLevel;
import courgette.api.CucumberOptions;
import courgette.api.testng.TestNGCourgette;
import io.cucumber.testng.AbstractTestNGCucumberTests;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
@Test
@CourgetteOptions(
        threads = 10,
        runLevel = CourgetteRunLevel.SCENARIO,
        rerunFailedScenarios = true,
        rerunAttempts = 1,
        showTestOutput = true,
        reportTitle = "Courgette-JVM Example",
        reportTargetDir = "build",
        environmentInfo = "browser=chrome; git_branch=master",
        cucumberOptions = @CucumberOptions(
                features = "src/test/resources/com/test/",
                glue = "com.test.stepdefs",                   
                publish = true,
                plugin = {
                        "pretty",
                        "json:target/cucumber-report/cucumber.json",
                        "html:target/cucumber-report/cucumber.html"}
        ))
class AcceptanceIT extends TestNGCourgette {
}

RemoteWebdriver 配置为

protected RemoteWebDriver createDriver() throws MalformedURLException , IOException {
                   
                 Properties properties = new Properties();                
                ClassLoader loader = Thread.currentThread().getContextClassLoader();                
                  String hubURL = "http://192.168.1.7:65299/wd/hub";
                  System.setProperty("webdriver.gecko.driver", "/Users/amit/Desktop/amit/projects/misc/geckodriver");
                 
                    FirefoxProfile profile = new FirefoxProfile();
                    DesiredCapabilities capabilities = DesiredCapabilities.firefox();
                    capabilities.setCapability(FirefoxDriver.PROFILE, profile);
                    capabilities.setPlatform(Platform.ANY);    
                    FirefoxOptions options = new FirefoxOptions();
                    options.merge(capabilities);                 
                   driver.set(new RemoteWebDriver(new URL(hubURL),options));
                   return driver.get();
        }

cucumber-guice 相关配置

    import io.cucumber.guice.ScenarioScoped;    
    @ScenarioScoped
          public class Global {
          public RemoteWebDriver driver;
           
          public Global() throws MalformedURLException, IOException {
                driver = new DriverFactory().getManager();
               // getManager() should have driver from above createDriver()

          }
    }

在您的 stepdef 中注入 Global class,如下所示(进行必要的导入)。您也可以注入 helper classes 并且 guice 将在每个场景中提供它

 @Inject
   Global global;
 
  //then you can do
   global.driver.get(site);

cucumber-guice 的 pom

 <dependency>
      <groupId>io.cucumber</groupId>
      <artifactId>cucumber-guice</artifactId>
      <version>${cucumber.version}</version>
      <scope>test</scope>
    </dependency>

如果您想使用 docker-compose 打开网格并将您的测试指向 http://localhost:65299/wd/hub ,请使用下面的配置。端口根据以下文件

version: "3"
services:
  selenium-hub:
    image: selenium/hub:3.141.59-20210607
    container_name: selenium-hub
    ports:
      - "65299:4444"

  chrome:
    image: selenium/node-chrome:3.141.59-20210607
    depends_on:
      - selenium-hub
    environment:
      - HUB_HOST=selenium-hub
      - HUB_PORT=4444


  firefox:
    image: selenium/node-firefox:3.141.59-20210607
    depends_on:
      - selenium-hub
    environment:
      - HUB_HOST=selenium-hub
      - HUB_PORT=4444
    deploy:
      mode: replicated
      replicas: 7