4

I'm using Cucumber and JUnit5 to write tests for my projects. My project uses Spring Framework and Gradle as a build tool and I use IntelliJ Idea as an editor which has Cucumber and Gradle plugins. Here is my Cucumber's runner:

package com.mycom.myproject.cucumber;

import static io.cucumber.junit.platform.engine.Constants.*;

import org.junit.platform.suite.api.*;

@Suite
@IncludeEngines("cucumber")
@SelectClasspathResource("src/test/resources")
@ConfigurationParameters({
            @ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "com.mycom.myproject.cucumber.steps"),
            @ConfigurationParameter(key = FEATURES_PROPERTY_NAME, value = "src/test/resources/cucumber"),
            @ConfigurationParameter(key = PLUGIN_PROPERTY_NAME, value = "html")
})
public class RunCucumberTest {
}

This is my cucumberBootstrap class:

package com.mycom.myproject.cucumber;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;

import com.mycom.myproject.Application;

import io.cucumber.spring.CucumberContextConfiguration;

@CucumberContextConfiguration
@SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, args = "spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,com.arkea.catalyst.kafka.spring.KafkaAutoConfiguration")
@ActiveProfiles({ "IC" })
public class CucumberBootstrap {
}

My steps definition class:

package com.mycom.myproject.cucumber.steps;

import static org.junit.jupiter.api.Assertions.assertTrue;

public class StepDefinition extends CucumberBootstrap {

    @Quand("I want to calculate my bill")
    public void iWantToCalculateMyBill() {
         // some code
    }

    @Alors("I have this result")
    public void iHaveThisResult() {
         // some assertions
    }
}

Here is my gradle.build file:

   // Tests dependencies
   testImplementation 'org.junit.jupiter:junit-jupiter-api'
   testImplementation 'org.junit.jupiter:junit-jupiter-engine'
   testImplementation 'org.springframework.boot:spring-boot-starter-test'
   testImplementation 'org.springframework.security:spring-security-test'
   testImplementation 'io.rest-assured:rest-assured:4.1.2'

   testImplementation "io.cucumber:cucumber-java:$cucumberVersion"
   testImplementation "io.cucumber:cucumber-spring:$cucumberVersion"
   testImplementation "io.cucumber:cucumber-junit-platform-engine:$cucumberVersion"

   testImplementation "org.junit.vintage:junit-vintage-engine"
   testImplementation 'org.junit.platform:junit-platform-suite:1.9.0'
   implementation 'org.junit.platform:junit-platform-commons:1.9.0'
}

test {
   useJUnitPlatform()
   systemProperty 'java.util.logging.manager', 'org.apache.logging.log4j.jul.LogManager'
   testLogging.showStandardStreams = true
   testLogging.exceptionFormat = 'full'
}

My cucumber's version is 7.5.0. No matter how I change the code, I keep having the "no tests found for given includes" error and I have no idea how to change it. Do you guys have any clue?

Thanks

dbaltor
  • 2,737
  • 3
  • 24
  • 36
  • In `@SelectClasspathResource("src/test/resources")` the `src/test/resources` doesn't look like a classpath entry. You also shouldn't use `FEATURES_PROPERTY_NAME`. Have a look at the https://cucumber.io/docs/guides/10-minute-tutorial/ for a minimal working example. – M.P. Korstanje Aug 10 '22 at 14:07
  • Hello, thank you for your comment. If it's not "src/test/resources", then what should it be? Can you give me the documentation? – Hải Trung Phạm Aug 10 '22 at 14:34
  • I believe most java courses should have covered what the classpath is. But either way, did you go through the tutorial? – M.P. Korstanje Aug 10 '22 at 14:51
  • Well, I see configurations.cucumberRuntime + sourceSets.main.output + sourceSets.test.output as classpath but the tutorial didn't mention junit5 – Hải Trung Phạm Aug 10 '22 at 15:09
  • I found this example helpful: https://github.com/cronn/cucumber-junit5-example – johanneslink Aug 11 '22 at 04:16
  • Ah sorry. Looks like the tutorial needs to be updated. The maven archetype uses JUnit 5 and converting that to a Gradle project gets you a working project. But that's not actually there. – M.P. Korstanje Aug 11 '22 at 12:59

2 Answers2

2

In your runner class you've got two problems.

Problem 1

@SelectClasspathResource("src/test/resources")

This selects a classpath resource. However src/test/resources is not a resource on the classpath.

To explain, consider a simple project you may have the following layout:

src
├── main
│   └── java
│       └── io
│           └── cucumber
│               └── skeleton
│                   └── Belly.java
└── test
    ├── java
    │   └── io
    │       └── cucumber
    │           └── skeleton
    │               ├── RunCucumberTest.java
    │               └── StepDefinitions.java
    └── resources
        ├── io
        │   └── cucumber
        │       └── skeleton
        │           └── belly.feature
        └── junit-platform.properties

Here src/main/java, src/test/java and src/test/resources are different sources. When you build your project these are compiled or copied the build folder:

build
├── classes
│   └── java
│       ├── main
│       │   └── io
│       │       └── cucumber
│       │           └── skeleton
│       │               └── Belly.class
│       └── test
│           └── io
│               └── cucumber
│                   └── skeleton
│                       ├── RunCucumberTest.class
│                       └── StepDefinitions.class
└── resources
    └── test
        ├── io
        │   └── cucumber
        │       └── skeleton
        │           └── belly.feature
        └── junit-platform.properties

Then when running your tests, the class path is composed of your dependencies and the build/classes/java/{main,test} and build/resources/test classpath roots.

This means that io/cucumber/{Belly,RunCucumberTest,StepDefinitions}.class as well as io/cucumber/skeleton/belly.feature are all resources on the classpath.

And because @SelectClasspathResource selects a class path resource you should use @SelectClasspathResource("io/cucumber/skeleton/belly.feature"). If you have multiple features in @SelectClasspathResource("io/cucumber/skeleton") will also work.

Problem 2

@ConfigurationParameter(key = FEATURES_PROPERTY_NAME, ..)

The FEATURES_PROPERTY_NAME only exists because Maven and Gradle don't support JUnit5s discovery selectors from the command line. You don't need it in this case.

M.P. Korstanje
  • 10,426
  • 3
  • 36
  • 58
  • Hello, I tried to implement your solution but it still gives me the same error. This time I removed the "key = FEATURE...." and change the classpath to "com/mycom/myproject" which is the classpath that I found inside the build folder – Hải Trung Phạm Aug 12 '22 at 09:16
  • Then maybe there is something else that doesn't match up. The https://github.com/cucumber/cucumber-java-skeleton contains a working example (with a failing test) for Gradle. You can compare against that one. Do make sure to use all the flags from the docs when using gradle `./gradlew test --rerun-tasks --info` otherwise Gradle won't show you the problem on the CLI. – M.P. Korstanje Aug 12 '22 at 10:06
1

You're pretty close!
In your RunCucumberTest class:

  1. Add
@SelectClasspathResource("features")
  1. Remove
@ConfigurationParameter(key = FEATURES_PROPERTY_NAME, value = "src/test/resources/cucumber"),

And then put your feature files under:

src/test/resources/features/

By the way, you don't need:

@IncludeEngines("cucumber")
dbaltor
  • 2,737
  • 3
  • 24
  • 36