Gradle and Maven (Surefire/Failsafe) support only class-based tests (gradle/#4773,
SUREFIRE-1724), which means that they can’t discover cucumbers *.feature
files as tests.
The recommended workaround is to create a single JUnit 5 suite class to run all the feature files.
This works fine, if your goal is to just always run all tests.
However, if you want to be able to run a single feature file or use advanced test acceleration techniques, such as Predictive Test Selection (PTS), or Test Distribution (TD), then you need to have a single test class per feature file.
This is where the Cucumber Companion plugins come in: they automate the creation of the necessary JUnit 5 suite files to allow a fine-grained selection of tests.
We think of the generated JUnit 5 suite files as companions to the respective Cucumber feature files. Also, the plugins don’t replace anything from Cucumber, but act as companions to it. Hence, we named the plugin Cucumber Companion.
This document assumes that you have followed the basic instructions from https://cucumber.io/docs/installation/java/ and https://github.com/cucumber/cucumber-jvm/tree/main/cucumber-junit-platform-engine to set up the necessary dependencies.
The Cucumber Companion plugin requires at least Gradle version 7.3.
Add the plugin declaration to the plugins block in your build.gradle(.kts)
file.
plugins {
id("com.gradle.cucumber.companion") version "1.2.0"
}
If your Cucumber feature files are in the standard src/test/resources
folder, this is all you have to do.
The plugin adds a testGenerateCucumberSuiteCompanion
task, which you can run manually to verify that the generation works.
If your build uses the JVM Test Suite Plugin, and your features are not in the default test-suite, then you can enable the companion file generation for other test suites as follows:
build.gradle.kts
(Kotlin)
testing {
suites {
functionalTest {
generateCucumberSuiteCompanion(project)
}
}
}
build.gradle
(Groovy)
testing {
suites {
functionalTest {
cucumberCompanion.generateCucumberSuiteCompanion(delegate)
}
}
}
The added companion task has the pattern of <suiteName>GenerateCucumberSuiteCompanion
, so for a suite named functionalTest
it would be functionalTestGenerateCucumberSuiteCompanion
.
However, there’s usually no need to call it manually since the compile<suiteName>Java
task depends on it.
If you need to disable the generation of companion files for the default test
task/suite, then you can do so via the cucumberCompanion
extension.
build.gradle.kts
(Kotlin)
cucumberCompanion {
enableForStandardTestTask.set(false)
}
build.gradle
(Groovy)
cucumberCompanion {
enableForStandardTestTask = false
}
This is interesting especially for test cases retries when all but few tests being filtered out.
It adds failIfNoTests = false
to the generated @Suite
annotation.
By default, companions execution will fail if all tests of a suite have been filtered out
in the JUnit5 discovery
phase.
See also Test Retry Gradle Plugin.
build.gradle.kts
(Kotlin)
cucumberCompanion {
allowEmptySuites.set(true)
}
build.gradle
(Groovy)
cucumberCompanion {
allowEmptySuites = true
}
For the same outcome at the test suite level, define:
build.gradle.kts
(Kotlin)
testing {
suites {
functionalTest {
generateCucumberSuiteCompanion(project) {
allowEmptySuites.set(true)
}
}
}
}
build.gradle
(Groovy)
testing {
suites {
functionalTest {
cucumberCompanion.generateCucumberSuiteCompanion(delegate) {
allowEmptySuites = true
}
}
}
}
Note that the configuration of a test suite will have higher priority than plugin-level configuration.
The plugin has been tested with Maven versions >= 3.8.6.
Add this plugin declaration to your pom.xml
.
The goal is bound to the generate-test-sources
lifecycle phase.
<build>
<plugins>
<plugin>
<groupId>com.gradle.cucumber.companion</groupId>
<artifactId>cucumber-companion-maven-plugin</artifactId>
<version>1.2.0</version>
<executions>
<execution>
<goals>
<goal>generate-cucumber-companion-files</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
By default, the plugin generates *Test.java
files for Surefire.
If you prefer to run your tests with Failsafe instead, then you can configure the plugin to use IT
as suffix instead.
<build>
<plugins>
<plugin>
<groupId>com.gradle.cucumber.companion</groupId>
<artifactId>cucumber-companion-maven-plugin</artifactId>
<version>1.2.0</version>
<executions>
<execution>
<goals>
<goal>generate-cucumber-companion-files</goal>
</goals>
<configuration>
<generatedFileNameSuffix>IT</generatedFileNameSuffix>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
This is interesting especially for test cases retries when all but few tests being filtered out.
It adds failIfNoTests = false
to the generated @Suite
annotation.
By default, companions execution will fail if all tests of a suite have been filtered out
in the JUnit5 discovery
phase.
<build>
<plugins>
<plugin>
<groupId>com.gradle.cucumber.companion</groupId>
<artifactId>cucumber-companion-maven-plugin</artifactId>
<version>1.2.0</version>
<executions>
<execution>
<goals>
<goal>generate-cucumber-companion-files</goal>
</goals>
<configuration>
<allowEmptySuites>true</allowEmptySuites>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>