Import Cucumber with Gradle - gradle

I want to import cucumber.api.java.en.* into my groovy files, but cucmber.api will not be recognized as in my classpath. Thus every #Given or #When annotation is not recognized.
When I build with ./gradlew cucumber the .feature file is found and missing snippets are shown in the console. What do I have to include in my build.gradle to add above import into my classpath?
My gradle version is 2.2 and the cucumber related parts of my build.gradle file look like this:
dependencies {
testCompile 'info.cukes:cucumber-java:1.2.4'
testCompile 'info.cukes:cucumber-junit:1.2.4'
}
test {
testLogging.showStandardStreams = true
systemProperties System.getProperties()
}
configurations {
cucumberRuntime {
extendsFrom testRuntime
}
}
task cucumber() {
dependsOn assemble, compileTestJava
doLast {
javaexec {
main = "cucumber.api.cli.Main"
classpath = configurations.cucumberRuntime + sourceSets.main.output + sourceSets.test.output
args = ['-f', 'pretty', '--glue', 'gradle.cucumber', 'src/test/resources']
}
}
}
What am I missing?

You include info.cukes:cucumber-java:1.2.4 which is the jar containing the annotations you are missing. They are expected to be available in your test classpath.
To me, it sounds as an issue with your IDE.
If you are using IntelliJ IDEA, try to re-import the project. Click on the two rotating arrows in your Gradle tab and refresh the project.

Related

Gradle 7: how to get list of implementation dependencies (including sub) in a task?

I need to have full list of dependencies necessary to run a project (so subdependencies are also important!).
task generateLibsDescriptor() {
doFirst {
configurations.compileClasspath.resolvedConfiguration.resolvedArtifacts.each {
println it
}
}
}
This code works, but there are also compileOnly dependencies listed. I tried to change compileClasspath to implementation, but had an error Resolving dependency configuration 'implementation' is not allowed as it is defined as 'canBeResolved=false'.
Is it possible to have a list of just implementation dependencies (with subdependencies)?
Configuration compileClasspath extends compileOnly and implementation. New config should be created which extends only implementation but resolvable.
configurations {
resolvableImpl.extendsFrom(implementation)
resolvableImpl.canBeResolved(true)
}
task generateLibsDescriptor() {
doFirst {
configurations.resolvableImpl.resolvedConfiguration.resolvedArtifacts.each {
println it
}
}
}

Creating a fat jar using Kotlin and Gradle - compile vs implementation?

I'm tinkering with a simple "hello world" project in Kotlin & Gradle (see below). I've added the "fat jar" collection stuff to bring in the Kotlin dependency, but when I try to run java -jar build/libs/hello-1.0-SNAPSHOT.jar I get the java.lang.NoClassDefFoundError: kotlin/jvm/internal/Intrinsics error because the dependencies aren't available at runtime.
I've solved that problem by changing implementation to compile, which makes everything work fine. But from what I understand, we shouldn't be using compile anymore, and neither api nor implementation makes the "fat jar" collection process work, and as I look at the other options for dependencies I'm not sure which to use.
Question: what's the "right" thing to do in a case like this?
// build.gradle
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.3.41'
}
group 'com.example.test'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
// if I change "implementation" to "compile", running the jar works
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
}
jar {
manifest {
attributes "Main-Class": "ApplicationKt"
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
}
// Application.kt
fun main(args: Array<String>) {
println("hello world")
}
The compile dependency is deprecated. You should use implementation to declare your implementation dependencies, and compileClasspath to get all the compilation dependencies.

Why do I need to specify 'from files'?

I was trying to build a jar out of my first groovy script. My project structure is as follows:
- build.gradle
- src\main\groovy\app\Test.groovy
My original gradle script:
apply plugin: 'groovy'
apply plugin: 'java'
repositories {
mavenCentral()
}
dependencies {
compile 'org.codehaus.groovy:groovy-all:2.3.11'
testCompile group: 'junit', name: 'junit', version: '4.11'
}
sourceSets.main.groovy.srcDirs = ["src/main/groovy"]
jar {
manifest {
attributes('Main-Class': 'app.Test')
}
}
From the guides I read, this should create a runnable jar. When I try to run it though I always get the error
Error: Could not find or load main class app.Test
I found out now that I need to add these two lines to the jar task:
from files(sourceSets.main.output.classesDir)
from configurations.runtime.asFileTree.files.collect { zipTree(it) }
The weird thing is that if I replace the groovy script with a Test.java class (same content), I don't need those two extra lines to run the jar.
I couldn't find out why I need them or what exactly they do. Can anyone explain that, or offer a documentation link?
I'm new to SO, please help me with my mistakes.
EDIT
The code suggested by tim_yates is translated to test.jar with the following content:
META-INF/MANIFEST.MF
Manifest-Version: 1.0
Main-Class: app.Test
app/Test.class
package app;
import groovy.lang.GroovyObject;
import groovy.lang.MetaClass;
import org.codehaus.groovy.runtime.callsite.CallSite;
public class Test implements GroovyObject {
public Test() {
CallSite[] var1 = $getCallSiteArray();
MetaClass var2 = this.$getStaticMetaClass();
this.metaClass = var2;
}
public static void main(String... args) {
CallSite[] var1 = $getCallSiteArray();
var1[0].callStatic(Test.class, "Hi!");
}
}
I execute with the following statement:
java -jar test.jar
Which results in the error message stated above.
You've got to remember that this jar contains Groovy compiled classes. The answer is in your decompiled source that you showed in the beginning. It imports Groovy runtime classes.
If you just run java -jar test.jar those classes are not on the classpath.
Either include groovy on the classpath of your command line or use the gradle application plugin to build a fat JAR (which is probably better for runnable jars) that contain all your application dependencies.
apply plugin: 'groovy'
apply plugin: 'application'
mainClassName='app.Test'
repositories {
mavenCentral()
}
dependencies {
compile 'org.codehaus.groovy:groovy-all:2.4.7'
testCompile 'junit:junit:4.12'
}
task uberjar(type: Jar,dependsOn:[':compileJava',':compileGroovy']) {
from files(sourceSets.main.output.classesDir)
from configurations.runtime.asFileTree.files.collect { zipTree(it) }
manifest {
attributes 'Main-Class': mainClassName
}
}
Then build your jar with gradle uberjar
Assuming Test.groovy looks something like:
package app
class Test {
static main(args) {
println "Hi!"
}
}
Then you only need the following build script:
apply plugin: 'groovy'
repositories {
mavenCentral()
}
dependencies {
compile 'org.codehaus.groovy:groovy-all:2.4.7'
testCompile 'junit:junit:4.12'
}
jar {
manifest {
attributes('Main-Class': 'app.Test')
}
}

Is there a Gradle task to download testRuntime dependencies?

Is there a command that will instruct Gradle to resolve and download all testRuntime dependencies, but not run the tests?
Preferably, I want to do this without writing a custom task (such that the command can be run against any Gradle project).
For example, if my build.gradle has this dependency:
dependencies {
// ...
testRuntime "org.seleniumhq.selenium:selenium-htmlunit-driver:2.47.1"
}
The JAR files associated with selenium-htmlunit-driver are not downloaded until I run gradle test, which also runs the tests. I can download all other dependencies by running gradle testClasses, but not the testRuntime deps.
Put the following in a file called resolve.gradle
gradle.allprojects { project ->
project.task('resolveTestRuntime') {
doLast {
project.configurations.testRuntime.resolve()
}
}
}
Then run resolve.gradle as an init script
gradlew --init-script resolve.gradle resolveTestRuntime
Modifying the answer from Lance Java into a valid Init script, I was able to accomplish this with the following resolve.gradle:
apply plugin:MyInitPlugin
class MyInitPlugin implements Plugin<Gradle> {
#Override
void apply(Gradle gradle) {
gradle.allprojects{ project ->
project.task('resolveTestRuntime') {
doLast {
project.configurations.testRuntime.resolve()
}
}
}
}
}
Then running:
gradlew --init-script resolve.gradle resolveTestRuntime

integrationTestCompile gradle dependency ignored

Following a few blog posts I tried to create a separate source folder for integration testing in gradle. I wanted also to add some additinal (arquillian) dependencies to my integrationTest task, but the integrationTestCompile seems to be ignored and I get a compilation error with the additional dependecy not resolved. When I change the dependecy to testCompile it works fine. Why is that so and how to change it? My simple test class:
//compilation fails with [Static type checking] - The variable [ArquillianSputnik] is undeclared
#TypeChecked
#RunWith(ArquillianSputnik)
class TestSpec extends Specification {
}
and gradle.build:
apply plugin: 'groovy'
apply plugin: 'war'
war.dependsOn 'native2ascii'
task native2ascii << {
ant.delete() {
fileset(dir: "${processResources.destinationDir}") {
include(name: '*.properties')
}
}
ant.native2ascii(src: 'src/main/resources/',
dest: "${processResources.destinationDir}",
includes: '**/*.properties',
encoding: 'UTF-8')
}
repositories {
mavenCentral()
maven {
url 'http://repository.jboss.org/nexus/content/groups/public'
}
mavenLocal()
}
sourceSets.main.java.srcDirs = []
sourceSets.main.groovy.srcDirs += ["src/main/java"]
sourceSets {
integrationTest {
groovy.srcDir file('src/integration-test/groovy')
resources.srcDir file('src/integration-test/resources')
compileClasspath = sourceSets.main.output + configurations.testCompile
runtimeClasspath = output + compileClasspath + configurations.testRuntime
}
}
dependencies {
//(...) non-test dependencies cut out for clarity
testCompile 'org.spockframework:spock-core:0.7-groovy-2.0'
testCompile 'cglib:cglib-nodep:2.2.2'
testCompile 'org.objenesis:objenesis:1.2'
//when integrationTestCompile is changed to testCompile the compilation works and the test is executed
integrationTestCompile 'org.jboss.arquillian.spock:arquillian-spock-container:1.0.0.Beta3'
integrationTestCompile 'org.jboss.arquillian.graphene:graphene-webdriver:2.0.3.Final'
integrationTestCompile 'org.jboss.as:jboss-as-arquillian-container-managed:7.2.0.Final'
}
task integrationTest(type: Test, dependsOn: 'test') {
testClassesDir = sourceSets.integrationTest.output.classesDir
classpath = sourceSets.integrationTest.runtimeClasspath
}
check.dependsOn 'integrationTest'
First, you want to add to the compile and runtime classpaths rather than replace them. This really just means using the += operator rather than the = one. Additionally, you really only want to add the other sourcesets output, we'll deal with configurations separately.
compileClasspath += sourcesets.main.output + sourcesets.test.output
runtimeClasspath += sourcesets.main.output + sourcesets.test.output
Next, we'll want to configure our integration test configurations. Usually, this just means making them extend the test and compile ones so that they contain all those dependencies as well.
configurations {
integrationTestCompile.extendsFrom testCompile
integrationTestRuntime.extendsFrom testRuntime
}

Resources