gradlecucumbercucumber-javacucumber-junitcucumber-spring

Importing multiple dependencies that have @CucumberContextConfigurations for leveraging their step definitions causes `CucumberBackendException`


I've been battling this issue for 2 days, but out of options I guess. I'm not a guru in Cucumber or Gradle, but since my area of expertise is close (Java/Spring/Maven), I've been working on updating multiple Gradle-based Cucumber projects to the latest versions of used frameworks. One of the issues I faced was io.cucumber.core.backend.CucumberBackendException: Please annotate a glue class with some context configuration. I resolved it by adding one such class per each of my projects like this:

@CucumberContextConfiguration
@ContextConfiguration("classpath:cucumber.xml")
public class CucumberSpringConfiguration
{

}

These configs were added to the same packages where step definitions reside, otherwise it was not visible since step definitions are specified via glue property of @CucumberOptions annotation in the test runner.

So it all worked in those projects until I started combining those together as dependencies. Imagine this: project A has some step definitions with its CucumberSpringConfiguration class defined. Project B has its own step definitions with its own CucumberSpringConfiguration class defined in the same package as its step definitions. Now project C imports A and B as its dependencies to leverage step definitions for an end to end test. And here the problem occurs:

io.cucumber.core.backend.CucumberBackendException: Glue class class com.projectA.core.stepdef.CucumberSpringConfiguration and class com.projectB.core.stepdef.CucumberSpringConfiguration are both (meta-)annotated with @CucumberContextConfiguration.
Please ensure only one class configures the spring context

What would be a way to resolve this? I thought about excluding those from the classpath like this (in build.gradle), but it did not work out:

tasks.withType(Test) {
    excludes = ['**/CucumberSpringConfiguration**']
    doFirst {

        // Get the current classpath
        def classpath = sourceSets.test.runtimeClasspath

        // Filter out the specific class file I want to exclude
        classpath = classpath.filter { file ->
            !file.absolutePath.contains("CucumberSpringConfiguration")
        }

        // Set the modified classpath
        setClasspath(files(classpath))
    }
}

I tried to move that CucumberSpringConfiguration in dependency projects out of that step definitions package, but since it's used in glue parameter of @CucumberOptions annotation in the test runner, it complains about necessity of having one.

Help from Cucumber/Gradle gurus is much needed here! Thank you very much in advance!


Solution

  • Project A, B and C each need a runner class and a class annotated with @CucumberContextConfiguration on the glue path. But they should not share those classes with other projects.

    Because you are making a library, the production code kept in src/main is shared but not the test code kept in src/test. So the glue code goes into src/main, and the runner and annotated class into src/test.