如何并行执行Cucumber功能文件



i在src/test/test/resources/feature/中具有以下功能文件(单独的功能文件),我想并行运行它们。像:一个功能文件必须在Chrome中执行,另一个功能文件必须在Firefox中执行,如上所述@tags名称。

Feature: Refund item
@chrome
  Scenario: Jeff returns a faulty microwave
    Given Jeff has bought a microwave for $100
    And he has a receipt
    When he returns the microwave
    Then Jeff should be refunded $100
Feature: Refund Money
@firefox
  Scenario: Jeff returns the money
    Given Jeff has bought a microwave for $100
    And he has a receipt
    When he returns the microwave
    Then Jeff should be refunded $100

有人可以帮助我实现这一目标。我使用cucumber-java 1.2.2版本,然后使用AS Runner使用AbspractTestNgcucumBertests。另外,让我知道如何通过使用功能文件动态创建测试跑步者并使它们并行运行。

update: 4.0.0版本可在Maven Central存储库中获得,并带有大量更改。有关更多详细信息,请转到此处。

更新: 2.2.0版本可在Maven Central存储库中获得。

您可以使用OpenSource插件Cucumber-JVM-Parallel-Plugin,该插件比现有解决方案具有许多优势。可在Maven存储库中获得

   <dependency>
     <groupId>com.github.temyers</groupId>
     <artifactId>cucumber-jvm-parallel-plugin</artifactId>
     <version>2.1.0</version>
   </dependency>
  1. 首先,您需要在项目pom文件中使用所需的配置添加此插件。

    <plugin>
      <groupId>com.github.temyers</groupId>
      <artifactId>cucumber-jvm-parallel-plugin</artifactId>
      <version>2.1.0</version>
      <executions>
         <execution>
         <id>generateRunners</id>
         <phase>generate-test-sources</phase>
         <goals>
           <goal>generateRunners</goal>
         </goals>
         <configuration>
             <!-- Mandatory -->
             <!-- comma separated list of package names to scan for glue code -->
             <glue>foo, bar</glue>
             <outputDirectory>${project.build.directory}/generated-test-sources/cucumber</outputDirectory>
              <!-- The directory, which must be in the root of the runtime classpath, containing your feature files.  -->
               <featuresDirectory>src/test/resources/features/</featuresDirectory>
              <!-- Directory where the cucumber report files shall be written  -->
              <cucumberOutputDir>target/cucumber-parallel</cucumberOutputDir>
              <!-- comma separated list of output formats json,html,rerun.txt -->
              <format>json</format>
              <!-- CucumberOptions.strict property -->
              <strict>true</strict>
              <!-- CucumberOptions.monochrome property -->
              <monochrome>true</monochrome>
              <!-- The tags to run, maps to CucumberOptions.tags property you can pass ANDed tags like "@tag1","@tag2" and ORed tags like "@tag1,@tag2,@tag3" -->
             <tags></tags>
             <!-- If set to true, only feature files containing the required tags shall be generated. -->
             <filterFeaturesByTags>false</filterFeaturesByTags>
             <!-- Generate TestNG runners instead of default JUnit ones. --> 
             <useTestNG>false</useTestNG>
             <!-- The naming scheme to use for the generated test classes.  One of 'simple' or 'feature-title' --> 
            <namingScheme>simple</namingScheme>
            <!-- The class naming pattern to use.  Only required/used if naming scheme is 'pattern'.-->
            <namingPattern>Parallel{c}IT</namingPattern>
            <!-- One of [SCENARIO, FEATURE]. SCENARIO generates one runner per scenario.  FEATURE generates a runner per feature. -->
            <parallelScheme>SCENARIO</parallelScheme>
            <!-- This is optional, required only if you want to specify a custom template for the generated sources (this is a relative path) -->
            <customVmTemplate>src/test/resources/cucumber-custom-runner.vm</customVmTemplate>
            </configuration>
           </execution>
         </executions>
       </plugin>
    
  2. 现在添加下面的插件下面的插件,该插件将调用上面插件生成的Runner类

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.19</version>
            <configuration> 
                <forkCount>5</forkCount>
                <reuseForks>true</reuseForks>
                <includes>
                    <include>**/*IT.class</include>
                </includes>
            </configuration>
        </plugin>
    
  3. 上面的两个插件将对并行运行的黄瓜测试做魔术(前提

  4. 严格提供的<forkCount>n</forkCount>这里'n'直接与1)高级硬件支持成正比,2)您可用节点,即注册的浏览器实例。

  5. 一个主要,最重要的更改是您的WebDriver类必须是共享,并且您应该 inashiment driver.quit()方法,因为关闭是要照顾的通过关闭钩。

    import cucumber.api.Scenario;
    import cucumber.api.java.After;
    import cucumber.api.java.Before;
    import org.openqa.selenium.OutputType;
    import org.openqa.selenium.WebDriver;
    import org.openqa.selenium.WebDriverException;
    import org.openqa.selenium.firefox.FirefoxDriver;
    import org.openqa.selenium.support.events.EventFiringWebDriver;
    public class SharedDriver extends EventFiringWebDriver {
        private static WebDriver REAL_DRIVER = null;
    
        private static final Thread CLOSE_THREAD = new Thread() {
            @Override
            public void run() {
                REAL_DRIVER.close();
            }
        };
        static {
            Runtime.getRuntime().addShutdownHook(CLOSE_THREAD);
        }
        public SharedDriver() {
            super(CreateDriver());
        }
        public static WebDriver CreateDriver() {
            WebDriver webDriver;
            if (REAL_DRIVER == null)
                webDriver = new FirefoxDriver();
            setWebDriver(webDriver);
            return webDriver;
        }
        public static void setWebDriver(WebDriver webDriver) {
            this.REAL_DRIVER = webDriver;
        }
        public static WebDriver getWebDriver() {
            return this.REAL_DRIVER;
        }
        @Override
        public void close() {
            if (Thread.currentThread() != CLOSE_THREAD) {
                throw new UnsupportedOperationException("You shouldn't close this WebDriver. It's shared and will close when the JVM exits.");
            }
            super.close();
        }
        @Before
        public void deleteAllCookies() {
            manage().deleteAllCookies();
        }
        @After
        public void embedScreenshot(Scenario scenario) {
            try {
                byte[] screenshot = getScreenshotAs(OutputType.BYTES);
                scenario.embed(screenshot, "image/png");
            } catch (WebDriverException somePlatformsDontSupportScreenshots) {
                System.err.println(somePlatformsDontSupportScreenshots.getMessage());
            }
        }
    }
    
  6. 考虑到您要执行超过50个线程,即浏览器实例没有注册到集线器,但是HUB如果没有足够的内存,将会死亡,以免避免这种关键情况,您应该使用-DPOOL_MAX启动HUB= 512(或更大),如Grid2文档中所述。

    Really large (>50 node) Hub installations may need to increase the jetty threads by setting -DPOOL_MAX=512 (or larger) on the java command line.

    java -jar selenium-server-standalone-<version>.jar -role hub -DPOOL_MAX=512

cucumber不支持盒子的并行执行。我已经尝试过,但它不友好。

  1. 我们必须使用Maven的能力并行调用。请参阅链接
  2. 还有一个GitHub项目,该项目使用自定义插件并行执行。请参阅Cucumber-JVM-Paralallel-Plugin

如果您期望的只是能够并行运行多个功能,那么您可以尝试执行以下操作:

  • 在您的测试项目中复制类AbstractTestngcucumbertests,并将属性parallel=true设置为@DataProvider注释方法。

由于来自TestNG的默认dataprovider-thread-count10,现在您已指示TestNG并行运行features,因此您应该开始并行看到功能文件。

但我知道黄瓜报告本质上不是线程安全的,因此您的报告可能会乱七八糟。

我使用 courgette-jvm实现了黄瓜并行性。它可以开箱即用,并在方案级别进行并行测试

只需在黄瓜中使用类似的跑步者类。我的测试进一步使用RemoteWebdriver在硒网格上打开多个实例。确保网格启动并运行,并将节点注册到网格中。

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();
        }

为了获得Testng的最大优势,您可以使用TestNG的第三方扩展QAF框架。它支持多种BDD语法,包括使用GherkinFactory。在与QAF一起使用BDD时,您可以利用每个测试NG功能,包括数据支持者,以不同方式(组/测试/方法),TestNG侦听器。

,并行执行配置。

QAF将每个方案视为测试测试和方案大纲作为测试NG数据驱动测试。由于QAF提供了内置驱动程序管理和资源管理,因此您无需为驱动程序管理或资源管理编写单行代码。您需要做的就是根据需要在一个或多个浏览器上创建测试XML配置文件。

它可以实现不同的可能配置组合。以下是XML 配置,可以解决此问题,它将在两个浏览器和并行运行方案。您也可以将每个浏览器的线程数配置为标准testng XML配置。

<suite name="AUT Test Automation" verbose="0"  parallel="tests">
<test name="Test-on-chrome">
   <parameter name="scenario.file.loc" value="resources/features" />
   <parameter name="driver.name" value="chromeDriver" />           
   <classes>
      <class name="com.qmetry.qaf.automation.step.client.gherkin.GherkinScenarioFactory" />
   </classes>
</test>
<test name="Test-on-FF">
   <parameter name="scenario.file.loc" value="resources/features" />
   <parameter name="driver.name" value="firefoxDriver" />           
   <classes>
      <class name="com.qmetry.qaf.automation.step.client.gherkin.GherkinScenarioFactory" />
   </classes>
</test>
</suite>

最新的BDDTestFactory2支持更多的语法,该语法源自QAF BDD,JBEHAVE和GHERKIN。它支持QAF BDD的元数据作为Gherkin的标签和示例。您可以使用bdd中的meta-data在XML/JSON/CSV/EXCEL/DB中利用内置数据支持者提供测试数据。

编辑:Cucumber-5用户可以利用QAF-Cucumber支持库。

由于Cucumber的V4,您可以无需扩展插件。

https://github.com/cucumber/cucumber-jvm/tree/main/main/cucumber-testng#parallel-execution

Cucumber Testng支持方案的并行执行。覆盖方案方法启用并行执行。

public class RunCucumberTest extends
AbstractTestNGCucumberTests {
    @Override
    @DataProvider(parallel = true)
    public Object[][] scenarios() {
        return super.scenarios();
    }
}

Maven Surefire插件配置用于并行执行

<plugins>    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-surefire-plugin</artifactId>
      <configuration>
         <properties>
            <property>
               <name>dataproviderthreadcount</name>
               <value>${threadcount}</value>
            </property>
         </properties>
      </configuration>    
   </plugin> 
</plugins> 

dataProviderThreadCount是要使用的默认线程数对于数据提供商,并并行运行测试。

最新更新