gradleazure-pipelinesjunit5cucumber-jvm

Execute cucumber feature files from devops pipeline


i am trying to run my cucumber feature files from a pipeline i created on devops. on my local machine, running the feature files works from the command line as expected using the following command:

./gradlew clean build test -PincludeTags="LoginFeature" --info

in my pipeline i am using this task

- task: Gradle@3
  inputs:
    gradleWrapperFile: 'gradlew'
    tasks: 'clean build test -PincludeTags="LoginFeature" --info'
  displayName: 'Testing'

and receiving this error:

CucumberTestRunner > initializationError FAILED
    org.junit.platform.suite.engine.NoTestsDiscoveredException: Suite [com.app.x.CucumberTestRunner] did not discover any tests
        at java.base@17.0.7/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
        at java.base@17.0.7/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
        at java.base@17.0.7/java.util.Iterator.forEachRemaining(Iterator.java:133)

if i execute the following instead:

- script: |

  chmod +x gradlew
  ./gradlew clean build test -PincludeTags="LoginFeature" --info

It works normally like on my local machine...

I am not sure why on DevOps pipeline the runner is not seeing the feature files... any help would be appreciated

my feature files are located in src/test/resources/com/app/x/features

this is my runner:

@Suite
@IncludeEngines("cucumber")
@SelectClasspathResource("com/app/x/features")
@SelectPackages(*arrayOf("com.app.x", "com.app.library"))
@ConfigurationParameter(key = io.cucumber.junit.platform.engine.Constants.GLUE_PROPERTY_NAME, value = "com.app.x,com.app.library")
@ConfigurationParameter(key = io.cucumber.junit.platform.engine.Constants.PLUGIN_PROPERTY_NAME,value = "pretty,summary,com.app.x.integrations.CucumberEventListener, html:target/cucumber-report/cucumber.html")
class CucumberTestRunner

and this is the gradle

import com.gradle.cucumber.companion.generateCucumberSuiteCompanion
import java.util.*

plugins {
    id("org.jetbrains.kotlin.jvm") version ("1.9.20")
    java
}

tasks {

    test {
        useJUnitPlatform {
           
            // OPTIONAL: Include only specified tags using JUnit5 tag expressions
            if (project.hasProperty("includeTags")) {
                println("project included includeTags: ${project.property("includeTags")}")
                includeTags(project.property("includeTags") as String?)
            } else {
                val properties = Properties()
                val configFile = System.getenv("configurationFile") ?: "configuration.properties"
                println("using configuration file: $configFile")
                file("src/test/resources/$configFile").inputStream().use { properties.load(it) }
                val tags = properties.getProperty("tags")
                println("project didnt include includeTags: $tags")
                includeTags(tags.replace("@", ""))
            }
        }
        // OPTIONAL: Ignore test failures so that build pipelines won't get blocked by failing examples/scenarios
        ignoreFailures = true
        // OPTIONAL: Copy all system properties from the command line (-D...) to the test environment
        systemProperties(project.gradle.startParameter.systemPropertiesArgs)
        // OPTIONAL: Enable parallel test execution
        systemProperty("cucumber.execution.parallel.enabled", true)
        // OPTIONAL: Set parallel execution strategy (defaults to dynamic)
        systemProperty("cucumber.execution.parallel.config.strategy", "fixed")
        // OPTIONAL: Set the fixed number of parallel test executions. Only works for the "fixed" strategy defined above
        systemProperty("cucumber.execution.parallel.config.fixed.parallelism", 4)
        // OPTIONAL: Enable Cucumber plugins, enable/disable as desired
        systemProperty("cucumber.plugin", "message:build/reports/cucumber.ndjson, timeline:build/reports/timeline, html:build/reports/cucumber.html")
        // OPTIONAL: Improve readability of test names in reports
        systemProperty("cucumber.junit-platform.naming-strategy", "long")
        // OPTIONAL: Force test execution even if they are up-to-date according to Gradle or use "gradle test --rerun"
        outputs.upToDateWhen { false }

        val reportsDir = file("$buildDir/test-results")
        outputs.dir(reportsDir)

        systemProperty("reports-dir", reportsDir)

        include("**/CucumberTestRunner.*")
    }
}

configurations {
    all {
        // OPTIONAL: Exclude JUnit 4
        exclude(group = "junit", module = "junit")
        // OPTIONAL: Exclude JUnit 5 vintage engine
        exclude(group = "org.junit.vintage", module = "junit-vintage-engine")
        // OPTIONAL: Exclude JUnit 5 jupiter engine
        exclude(group = "org.junit.jupiter", module = "junit-jupiter-engine")
    }
}
kotlin {
    sourceSets {
        val main by getting {
            kotlin.srcDir("src/main/kotlin")
            resources.srcDir("src/main/resources")
        }
        val test by getting {
            kotlin.srcDir("src/test/kotlin") // Ensure this is set correctly
            resources.srcDir("src/test/resources")
        }
    }
}

I tried adding

 id("com.gradle.cucumber.companion") version "1.3.0" 

from https://github.com/gradle/cucumber-companion?tab=readme-ov-file

but its not clear what it does and anyway it had no effect.


Solution

  • I ended up creating a regular script and just using gradlew like i would on the terminal on my local machine which worked as intended