I try to create an executable jar for my cucumber kotlin application but it prints in log that all scenarios are undefined:
...
3 Scenarios (3 undefined)
8 Steps (5 skipped, 3 undefined)
...
The application can be executed correctly from command line or from IntelliJ
Entry point of program:
package dsdms.client
import io.cucumber.core.cli.Main
class Main{
companion object{
@JvmStatic
fun main(args: Array<String>) {
Main.main("-p", "pretty",
"--glue", "dsdms.client.cucumber",
"--plugin", "html:build/reports/cucumber",
"classpath:features")
println("Hello Worldddd2!")
}
}
}
For project building I use Gradle with kotlin DSL
I tried to use first src/test
and then src/main
folders but even if I can execute all correctly form console it doesn't work for the jar execution
For fat jar generation I use:
tasks.withType<Jar> {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
manifest {
attributes["Main-Class"] = "dsdms.client.Main"
}
dependsOn(configurations.runtimeClasspath)
from({
configurations.runtimeClasspath.get().filter { it.name.endsWith("jar") }.map { zipTree(it) }
})
destinationDirectory.set(file("$buildDir/output"))
}
Jar file from inside seems to have all files needed for execution screenshot of jar file in zip format
Here link to repository that reproduce my problem. It also contains a jar file produced by project
When creating your jar file you've set duplicatesStrategy = DuplicatesStrategy.EXCLUDE
so any duplicate files will get ignored.
If you set:
duplicatesStrategy = DuplicatesStrategy.WARN
You'll see that:
> Task :SystemTester:jar
Encountered duplicate path "META-INF/versions/9/module-info.class" during copy operation configured with DuplicatesStrategy.WARN
Encountered duplicate path "META-INF/services/io.cucumber.core.backend.BackendProviderService" during copy operation configured with DuplicatesStrategy.WARN
Encountered duplicate path "META-INF/versions/9/module-info.class" during copy operation configured with DuplicatesStrategy.WARN
Encountered duplicate path "META-INF/versions/9/module-info.class" during copy operation configured with DuplicatesStrategy.WARN
And these warnings matter! To understand why it is important to understand what these files do. So it would be worth reading the JAR File Specification.
But in short for your problem, this is the warning that matters:
Encountered duplicate path "META-INF/services/io.cucumber.core.backend.BackendProviderService" during copy operation configured with DuplicatesStrategy.WARN
Because if you look at your dependencies you can see that you've got:
[libraries]
cucumber-java = {module = "io.cucumber:cucumber-java", version.ref="cucumber"}
...
cucumber-java8 = {module = "io.cucumber:cucumber-java8", version.ref="cucumber"}
Both of which include the META-INF/services/io.cucumber.core.backend.BackendProviderService
file.
For cucumber-java
this file contains:
io.cucumber.java.JavaBackendProviderService
While for cucumber-java8
it contains:
io.cucumber.java8.Java8BackendProviderService
These tell Cucumber what which services it has available to detect step definitions (i.e. it lets Cucumber know you using annotations or lambdas)`.
Now if you unzip the jar file you've made (you can do this using your favorite zip application) you'll find it only contains the BackendProviderService
registration for cucumber-java
and not the one for cucumber-java8
. As such your step definitions are not loaded because Cucumber doesn't it understands lambda step definitions.
The quick, and wrong way, to fix this would be to remove cucumber-java
as a dependency. But you may run into other problems of a similar nature. So your best option would be to expand your Gradle task to merge META-INF/services
files.
How? Not a clue. I don't use Gradle.