How to run cucumber-jvm tests using Gradle - cucumber

I am trying to get a project going using the new Cucumber-jvm system and Gradle as my build system.
I have used the example Java code in the GitHub cucumber-jvm project(https://github.com/cucumber/cucumber-jvm).
My project is set up in IntelliJ and the IDE is able to run the test.
However, Gradle does not find any tests to run. I know this because I broke the test and Gradle said nothing. It also said nothing when it was working.
The class it is trying to run looks like this:
import cucumber.junit.Cucumber;
import cucumber.junit.Feature;
import org.junit.runner.RunWith;
#RunWith(Cucumber.class)
#Feature(value = "CarMaintenance.feature")
public class FuelCarTest {
}
I'm new to both cucumber and Gradle!!

I remember having trouble with Gradle and Cucumber with the junit runner.
I eventually gave up and created a gradle task using the command line runner.
task executeFeatures(type: JavaExec, dependsOn: testClasses) {
main = "cucumber.cli.Main"
classpath += files(sourceSets.test.runtimeClasspath, file(webAppDir.path + '/WEB-INF/classes'))
args += [ '-f', 'html:build/reports/cucumber', '-g', 'uk.co.filmtrader', 'src/test/resources/features']
}
-f Folder for html report output
-g Package name for glue/step code
src/test/resources/features Where the feature files are
With the following dependencies
testCompile 'org.mockito:mockito-all:1.9.5',
'junit:junit:4.11',
'org.hamcrest:hamcrest-library:1.3',
'info.cukes:cucumber-java:1.0.14',
'info.cukes:cucumber-junit:1.0.14',
'info.cukes:cucumber-spring:1.0.14'
Update for version 4.2.5
There had been some minor changes over time:
the package name of the cli changed to cucumber.api.cli.Main
The flag -f seems no longer to be working and causes an error
So I ended up with the following task definition in my build.gradle:
task executeFeatures(type: JavaExec, dependsOn: testClasses) {
main = "cucumber.api.cli.Main"
classpath += files(sourceSets.test.runtimeClasspath)
args += [ '-g', 'uk.co.filmtrader', 'src/test/resources/features']
}

other way can be to create a task and include runner class for test
build.gradle-
task RunCukesTest(type: Test) << {
include "RunCukesTest.class"
}
testCompile 'io.cucumber:cucumber-java:4.2.0'
testCompile 'io.cucumber:cucumber-junit:4.2.0'
your class -
#RunWith(Cucumber.class)
#CucumberOptions(dryRun = false, strict = true, features = "src/test/resources", glue
= "com.gradle.featuretests",monochrome = true)
public class RunCukesTest {
}
simply hit the command :- gradle RunCukesTest

Considering:
Your .feature files are in src/test/resources/cucumber/features and
your glue classes are in com.example.myapp.glue
Then, following what is explained in the docs, you can do in build.gradle:
dependencies {
// ...
testImplementation("io.cucumber:cucumber-java:6.2.2")
testImplementation("io.cucumber:cucumber-junit:6.2.2")
testImplementation("io.cucumber:cucumber-junit-platform-engine:6.2.2")
}
configurations {
cucumberRuntime {
extendsFrom testImplementation
}
}
// this enables the task `gradle cucumber`
task cucumber() {
dependsOn assemble, compileTestKotlin
doLast {
javaexec {
main = "io.cucumber.core.cli.Main"
classpath = configurations.cucumberRuntime + sourceSets.main.output + sourceSets.test.output
args = ['--strict', '--plugin', 'pretty', '--plugin', 'junit:build/test-results/cucumber.xml', '--glue', 'com.example.myapp.glue', 'src/test/resources/cucumber/features']
}
}
}
// (OPTIONAL) this makes `gradle test` also include cucumber tests
tasks.test {
finalizedBy cucumber
}
Now gradle cucumber will run the cucumber tests.
If you added the last part, gradle test will also run cucumber tests.
The args part supports what goes in the #CucumberOptions annotation of the runner. More details: https://cucumber.io/docs/cucumber/api/#list-configuration-options

Related

nebula-test fails to load the project plugin class when using IntegrationSpec class

I'm in the process of writing and testing a Gradle plugin. When I try to test the plugin I get an error indicating the plugin class can't be found? If I use the plugin id I get: Plugin with id <> not found. If I use the plugin class name I get: Could not find property 'com' on root project.
Below is the build.gradle, ExamplePlugin class and the Test Spec.
build.gradle
apply plugin: 'idea'
apply plugin: 'groovy'
apply plugin: 'maven'
group = 'com.sas'
version = '0.1.0'
description = "Project to test with nebula plugin."
task wrapper(type: Wrapper) {
gradleVersion = '2.6' //version required
}
repositories {
jcenter()
mavenCentral()
}
dependencies {
compile localGroovy()
compile gradleApi()
testCompile 'org.spockframework:spock-core:1.0-groovy-2.3'
testCompile 'com.netflix.nebula:nebula-test:3.1.0'
}
plugin class
package com.sas.gradle.plugins.example
import org.gradle.api.Plugin
import org.gradle.api.Project
class ExamplePlugin implements Plugin<Project> {
#Override
void apply(Project project) {
project.logger.debug("ExamplePlugin: Running...")
}
}
test class spec
package com.sas.gradle.plugins.example
import nebula.test.IntegrationSpec
import nebula.test.functional.ExecutionResult
class ExamplePluginIntegSpec extends IntegrationSpec {
def 'setup and display the buildscript classpath'() {
writeHelloWorld('example.hello')
buildFile << '''
apply plugin: 'java'
apply plugin: com.sas.gradle.plugins.example.ExamplePlugin
task show << {
buildscript.configurations.classpath.each { println it }
}
'''.stripIndent()
when:
ExecutionResult result = runTasksSuccessfully('show')
then:
result.standardOutput.contains(':show')
}
}
It appears when using the IntegrationSpec it creates build scripts build.gradle and settings.gradle in build/test/package/spec location. Also, I see .gradle, .gradle-test-kit, src directories at the same location. I was wondering how the .classpath is setup for running the tests and noticed an init.gradle script in the .gradle-test-kit; then in it I found a allprojects->buildscript->dependencies>classpath DSL.
Then I noticed my plugin class (compiled to build/classes/main) wasn’t in the list? I’d have thought nebula-test IntegrationSpec class would have done this? By adding this DSL:
buildscript {
dependencies {
classpath files('../../../../build/classes/main')
}
}
Thanks in advance for any help,
Jim
Lastly here's the exception I get:
Class com.sas.gradle.plugins.example.ExamplePluginIntegSpec
all > com.sas.gradle.plugins.example > ExamplePluginIntegSpec
1
tests
1
failures
0
ignored
3.173s
duration
0%
successful
Failed tests
Tests
Standard output
Standard error
setup and display the buildscript classpath
org.gradle.api.GradleException: Build aborted because of an internal error.
at nebula.test.functional.internal.DefaultExecutionResult.rethrowFailure(DefaultExecutionResult.groovy:97)
at nebula.test.IntegrationSpec.runTasksSuccessfully(IntegrationSpec.groovy:265)
at com.sas.gradle.plugins.example.ExamplePluginIntegSpec.setup and display the buildscript classpath(ExamplePluginIntegSpec.groovy:19)
Caused by: org.gradle.internal.exceptions.LocationAwareException: Build file 'C:\Users\japoli\IdeaProjects\nebula-test-example-master\build\test\com.sas.gradle.plugins.example.ExamplePluginIntegSpec\setup-and-display-the-buildscript-classpath\build.gradle' line: 4
A problem occurred evaluating root project 'setup-and-display-the-buildscript-classpath'.
at org.gradle.initialization.DefaultExceptionAnalyser.transform(DefaultExceptionAnalyser.java:74)
at org.gradle.initialization.MultipleBuildFailuresExceptionAnalyser.transform(MultipleBuildFailuresExceptionAnalyser.java:47)
at org.gradle.initialization.StackTraceSanitizingExceptionAnalyser.transform(StackTraceSanitizingExceptionAnalyser.java:30)
at org.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradleLauncher.java:105)
at org.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradleLauncher.java:97)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:90)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:62)
at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:97)
at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:86)
at org.gradle.launcher.exec.InProcessBuildActionExecuter$DefaultBuildController.run(InProcessBuildActionExecuter.java:102)
at org.gradle.tooling.internal.provider.runner.BuildModelActionRunner.run(BuildModelActionRunner.java:46)
at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
at org.gradle.tooling.internal.provider.runner.SubscribableBuildActionRunner.run(SubscribableBuildActionRunner.java:58)
at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:47)
at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:32)
at org.gradle.launcher.exec.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:77)
at org.gradle.launcher.exec.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:47)
at org.gradle.tooling.internal.provider.DaemonBuildActionExecuter.execute(DaemonBuildActionExecuter.java:52)
at org.gradle.tooling.internal.provider.DaemonBuildActionExecuter.execute(DaemonBuildActionExecuter.java:35)
at org.gradle.tooling.internal.provider.LoggingBridgingBuildActionExecuter.execute(LoggingBridgingBuildActionExecuter.java:63)
at org.gradle.tooling.internal.provider.LoggingBridgingBuildActionExecuter.execute(LoggingBridgingBuildActionExecuter.java:35)
at org.gradle.tooling.internal.provider.ProviderConnection.run(ProviderConnection.java:124)
at org.gradle.tooling.internal.provider.ProviderConnection.run(ProviderConnection.java:100)
at org.gradle.tooling.internal.provider.DefaultConnection.getModel(DefaultConnection.java:167)
at org.gradle.tooling.internal.consumer.connection.CancellableModelBuilderBackedModelProducer.produceModel(CancellableModelBuilderBackedModelProducer.java:58)
at org.gradle.tooling.internal.consumer.connection.AbstractConsumerConnection.run(AbstractConsumerConnection.java:58)
at org.gradle.tooling.internal.consumer.DefaultBuildLauncher$1.run(DefaultBuildLauncher.java:84)
at org.gradle.tooling.internal.consumer.DefaultBuildLauncher$1.run(DefaultBuildLauncher.java:78)
at org.gradle.tooling.internal.consumer.connection.LazyConsumerActionExecutor.run(LazyConsumerActionExecutor.java:83)
at org.gradle.tooling.internal.consumer.connection.ProgressLoggingConsumerActionExecutor.run(ProgressLoggingConsumerActionExecutor.java:58)
at org.gradle.tooling.internal.consumer.connection.RethrowingErrorsConsumerActionExecutor.run(RethrowingErrorsConsumerActionExecutor.java:38)
at org.gradle.tooling.internal.consumer.async.DefaultAsyncConsumerActionExecutor$1$1.run(DefaultAsyncConsumerActionExecutor.java:55)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54)
at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:40)
Caused by: org.gradle.api.GradleScriptException: A problem occurred evaluating root project 'setup-and-display-the-buildscript-classpath'.
at org.gradle.groovy.scripts.internal.DefaultScriptRunnerFactory$ScriptRunnerImpl.run(DefaultScriptRunnerFactory.java:93)
at org.gradle.configuration.DefaultScriptPluginFactory$ScriptPluginImpl$1.run(DefaultScriptPluginFactory.java:148)
at org.gradle.configuration.ProjectScriptTarget.addConfiguration(ProjectScriptTarget.java:72)
at org.gradle.configuration.DefaultScriptPluginFactory$ScriptPluginImpl.apply(DefaultScriptPluginFactory.java:153)
at org.gradle.configuration.project.BuildScriptProcessor.execute(BuildScriptProcessor.java:38)
at org.gradle.configuration.project.BuildScriptProcessor.execute(BuildScriptProcessor.java:25)
at org.gradle.configuration.project.ConfigureActionsProjectEvaluator.evaluate(ConfigureActionsProjectEvaluator.java:34)
at org.gradle.configuration.project.LifecycleProjectEvaluator.evaluate(LifecycleProjectEvaluator.java:55)
at org.gradle.api.internal.project.AbstractProject.evaluate(AbstractProject.java:495)
at org.gradle.api.internal.project.AbstractProject.evaluate(AbstractProject.java:89)
at org.gradle.execution.TaskPathProjectEvaluator.configureHierarchy(TaskPathProjectEvaluator.java:42)
at org.gradle.configuration.DefaultBuildConfigurer.configure(DefaultBuildConfigurer.java:35)
at org.gradle.initialization.DefaultGradleLauncher$2.run(DefaultGradleLauncher.java:129)
at org.gradle.internal.Factories$1.create(Factories.java:22)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:90)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:52)
at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:126)
at org.gradle.initialization.DefaultGradleLauncher.access$200(DefaultGradleLauncher.java:36)
at org.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradleLauncher.java:103)
... 31 more
Caused by: groovy.lang.MissingPropertyException: Could not find property 'com' on root project 'setup-and-display-the-buildscript-classpath'.
at org.gradle.api.internal.AbstractDynamicObject.propertyMissingException(AbstractDynamicObject.java:43)
at org.gradle.api.internal.AbstractDynamicObject.getProperty(AbstractDynamicObject.java:35)
at org.gradle.api.internal.CompositeDynamicObject.getProperty(CompositeDynamicObject.java:97)
at org.gradle.groovy.scripts.BasicScript.propertyMissing(BasicScript.java:66)
at build_3ap3e1c6wmmpxvu497fssx7g9.run(C:\Users\japoli\IdeaProjects\nebula-test-example-master\build\test\com.sas.gradle.plugins.example.ExamplePluginIntegSpec\setup-and-display-the-buildscript-classpath\build.gradle:4)
at org.gradle.groovy.scripts.internal.DefaultScriptRunnerFactory$ScriptRunnerImpl.run(DefaultScriptRunnerFactory.java:91)
... 49 more
Wrap lines
Generated by Gradle 2.6 at Jan 13, 2016 10:01:59 AM
Have you taken a look at Gradle TestKit (the functional replacement for Nebula test)? Take a look at the specific section about placing the code under test on the classpath.

Unusually low test coverage reported when using Cobertura with Gradle and Groovy code

I'm developing a Gradle plugin and I'm trying to configure my project to let me get code coverage metrics on it. I have unit and integration tests based on the Spock framework.
I've tried using both Jacoco and Cobertura to analyse my project. Here is the configuration I'm working with:
Gradle: 2.2.1
Groovy: 2.3.6
Ant: Apache Ant(TM) version 1.9.3 compiled on December 23 2013
JVM: 1.8.0_25 (Oracle Corporation 25.25-b02)
OS: Mac OS X 10.10.1 x86_64
I'm using the gradle-cobertura-plugin v2.2.5.
Cobertura
In the case of Cobertura, my project's reported line coverage is only 35%. There are large sections of code that I have written tests for that are reported as not tested by Cobertura:
In particular, Cobertura reports no coverage for the nested static class Version.Parser despite there being a complete Spock specification devoted to this:
package com.github.tagc.semver
import spock.lang.Specification
import spock.lang.Unroll
import com.github.tagc.semver.Version.Parser
#Unroll
class VersionParserSpec extends Specification {
private static final Parser PARSER = Version.Parser.getInstance()
def "Version information should be extracted from files if parsing is not strict"() {
given:
def versionFileText = "version='$versionString'"
expect:
PARSER.parse(versionFileText, false) == version
where:
versionString | version
'0.1.2-SNAPSHOT' | new Version(0,1,2,false)
'1.2.4' | new Version(1,2,4,true)
'1.3-SNAPSHOT' | new Version(1,3,0,false)
'0.4' | new Version(0,4,0,true)
}
def "Valid version representation should be parsed successfully"() {
expect:
PARSER.parse(input, true) == version
where:
input | version
'0.1' | new Version(0,1,0,true)
'1.3-SNAPSHOT' | new Version(1,3,0,false)
'1.1.1' | new Version(1,1,1,true)
'0.2.7' | new Version(0,2,7,true)
'0.4.9-SNAPSHOT' | new Version(0,4,9,false)
'6.3.16-SNAPSHOT' | new Version(6,3,16,false)
' 1.2.3-SNAPSHOT' | new Version(1,2,3,false)
' 1.3.5-SNAPSHOT ' | new Version(1,3,5,false)
}
def "Invalid version representation (#input) should cause an exception to be thrown"() {
when:
PARSER.parse(input, true)
then:
thrown(IllegalArgumentException)
where:
input << [
'1.2.a',
'1,2,3',
'2.4.-1',
'3-4-9',
'1.4.5-SNPSHOT',
'1.4.5-SNAPSHOTasd'
]
}
}
Below are the relevant parts of my Gradle build script:
buildscript {
repositories { jcenter() }
dependencies {
// Cobertura plugin
classpath "net.saliman:gradle-cobertura-plugin:2.2.5"
}
}
configurations.all {
resolutionStrategy {
force 'org.ow2.asm:asm:5.0.3'
forcedModules = [ 'org.ow2.asm:asm:5.0.3' ]
}
}
apply plugin: 'net.saliman.cobertura'
check.dependsOn 'cobertura'
cobertura {
coverageFormats = [ 'html', 'xml' ]
}
Jacoco
In comparison, Jacoco reports a much more plausible coverage of 68% (by instructions).
Coverage of the same Version.Parser section is reported as this:
The relevant parts of my build script are:
apply plugin: "jacoco"
task integrationTest(type: Test) {
description = 'Runs the integration tests.'
group = 'verification'
testClassesDir = sourceSets.integrationTest.output.classesDir
classpath = sourceSets.integrationTest.runtimeClasspath
jacoco {
destinationFile = file("$buildDir/jacoco/integrationTest.exec")
classDumpFile = file("$buildDir/classes/integrationTest")
}
}
jacocoTestReport {
executionData test, integrationTest
reports {
xml.enabled true
html.enabled true
}
}
Since Jacoco seems to be working fine, I'd ideally like to just stick with it. However, Sonar doesn't seem to work properly with Jacoco when writing code in Groovy, so I seem to be stuck with Cobertura. Is there any reason why Cobertura could be giving me these coverage results?
EDIT
I have raised this as an issue on the Gradle Cobertura plugin Github repository.
I haven't tested it myself but apparently this issue is fixed as of v2.2.7 of the Gradle plugin, which uses v2.1.1 of Cobertura (source).

How to build Groovy JAR w/ Gradle and publish it to in-house repo

I have a Groovy project and am trying to build it with Gradle. First I want a package task that creates a JAR by compiling it against its dependencies. Then I need to generate a Maven POM for that JAR and publish the JAR/POM to an in-house Artifactory repo. The build.gradle:
apply plugin: "groovy"
apply plugin: "maven-publish"
repositories {
maven {
name "artifactory01"
url "http://myartifactory/artifactory/libs-release"
}
}
dependencies {
compile "long list starts here"
}
// Should compile up myapp-<version>.jar
jar {
}
// Should publish myapp-<version>.jar and its (generated) POM to our in-house Maven/Artifactory repo.
publishing {
publications {
myPublication(MavenPublication) {
from components.java
artifact sourceJar {
classifier "source"
}
pom.withXml {
// ???
}
}
}
}
task wrapper(type: Wrapper) {
gradleVersion = '1.11'
}
However I do not believe I have set up versioning correctly with my jar task (for instance, how could I get it creating myapp-1.2.1 vs. myapp-1.2.2? I also don't think I have my publications configuration set up correctly: what should go in pom.withXml?
You're more than welcome to use artifactory plugin for that.
The documentation can be found in our user guide and below you can find a full working example of gradle build.
Run gradle build artifactoryPublish to build and publish the project.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath(group: 'org.jfrog.buildinfo', name: 'build-info-extractor-gradle', version: '3.0.1')
}
}
apply plugin: 'java'
apply plugin: 'maven-publish'
apply plugin: 'com.jfrog.artifactory'
group = 'com.jfrog.example'
version = '1.2-SNAPSHOT'
status = 'SNAPSHOT'
dependencies {
compile 'org.slf4j:slf4j-api:1.7.5'
testCompile 'junit:junit:4.11'
}
task sourcesJar(type: Jar, dependsOn: classes) {
classifier = 'sources'
from sourceSets.main.allSource
}
publishing {
publications {
main(MavenPublication) {
from components.java
artifact sourcesJar
}
}
artifactory {
contextUrl = 'http://myartifactory/artifactory'
resolve {
repository {
repoKey = 'libs-release'
}
}
publish {
repository {
repoKey = 'libs-snapshot-local'
username = 'whatever'
password = 'whatever123'
}
defaults {
publications 'main'
}
}
}
package is a keyword in Java/Groovy, and you'd have to use a different syntax to declare a task with that name.
Anyway, the task declaration for package should be removed, as the jar task already serves that purpose. The jar task configuration (jar { from ... }) should be at the outermost level (not nested inside another task), but from configurations.compile is unlikely what you want, as that will include Jars of compile dependencies into the Jar (which regular Java class loaders can't deal with), rather than merging them into the Jar. (Are you even sure you need a fat Jar?)
Likewise, the publish task declaration should be removed, and replaced with publishing { publications { ... } }.
Also, the buildscript block should probably be removed, and repositories { ... } and dependencies { ... } moved to the outermost level. ( buildscript { dependencies { ... } } declares dependencies of the build script itself (e.g. Gradle plugins), not the dependencies of the code to be compiled/run.)
I suggest to check out the many self-contained example builds in the samples directory of the full Gradle distribution (gradle-all).

Run Single Test in Cucumber Groovy

I wanted to run single test in cucumber/groovy following is the structure.
If I want to run single test scenario e.g. Scenario: Change culture as marked in the screen shot in the command line, how should I run it?
I tried following >gradle -Dtest.single=home-page test and few other options by giving full path and with extention(.feature), but there was no luck.
build.gradle
apply plugin: "groovy"
apply plugin: "idea"
repositories {
mavenCentral()
}
sourceCompatibility = 1.6
targetCompatibility = 1.6
def version = [
'groovy' : '1.8.6',
'junit' : '4.10',
'geb' : '0.7.2',
'selenium' : '2.25.0',
'cucumber' : '1.0.8'
]
ext.drivers = ["htmlunit", "firefox", "chrome"]
dependencies {
groovy "org.codehaus.groovy:groovy-all:$version.groovy"
testCompile "junit:junit:$version.junit"
testCompile "org.codehaus.geb:geb-junit4:$version.geb"
testCompile "info.cukes:cucumber-groovy:$version.cucumber"
testCompile "info.cukes:cucumber-junit:$version.cucumber"
// Drivers
drivers.each { driver ->
testCompile "org.seleniumhq.selenium:selenium-$driver-driver:$version.selenium"
}
}
1st step: annotate the scenario like below:
#culture
Scenario: Scenario Description
Given ....
When .....
Then ....
2nd step: use gradle-cucumber-plugin
3rd step: edit cucumber task configuration to run scenario with #culture tag
cucumber {
formats = [
'pretty',
'html:build/reports/cucumber',
'junit:build/cucumber.xml'
]
tags = ['#culture', '#other_tag']
dryRun = false
monochrome = false
strict = false
}

How to make a task to call a main class

What I am trying to do is make a task in build.gradle that will execute a main class (class with the main method), but I don't know how.
I made a test project to test how to do that. Here is the file structure layout:
testProject/
build.gradle
src/main/groovy/hello/world/HelloWorld.groovy
Here is the content of build.gradle:
apply plugin: 'groovy'
apply plugin: 'maven'
repositories {
mavenCentral()
}
dependencies {
compile 'org.codehaus.groovy:groovy-all:2.0.6'
}
task( hello, dependsOn: jar, type: JavaExec ) {
main = 'hello.world.HelloWorld'
}
Here is the content of HelloWorld.groovy:
package hello.world
class HelloWorld {
public static void main(String[] args) {
println "Hello World!"
}
}
Here is what I get from shell:
testProject>$ gradle hello
:compileJava UP-TO-DATE
:compileGroovy UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:jar UP-TO-DATE
:hello
Error: Could not find or load main class hello.world.HelloWorld
:hello FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':hello'.
> Process 'command '/Library/Java/JavaVirtualMachines/jdk1.7.0_25.jdk/Contents/Home/bin/java'' finished with non-zero exit value 1
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
BUILD FAILED
Total time: 4.232 secs
So, my question is: how can I make gradle hello work? Thank you very much.
After a bit of googling, I found a solution. The only thing I need to change is the task block. The working one is pasted below:
task( hello, dependsOn: jar, type: JavaExec ) {
main = 'hello.world.HelloWorld'
classpath = sourceSets.main.runtimeClasspath
}
There is an application plugin for doing this.
apply plugin: 'application'
mainClassName = 'hello.world.HelloWorld'
And then call
gradle run
Besides adding run task, applying application plugin will also change the behaviour of assemble task. Now it will produce a standalone application that can be run with a shell script.
Consider this build.gradle, which is a simplified version:
apply plugin: 'groovy'
task( hello, type: JavaExec ) {
main = 'hello.world.HelloWorld'
classpath = files('exampleDir/bin','jars/groovy-all-2.0.1.jar')
}
Note the 'classpath' argument to the JavaExec task. This uses subdirectories such as:
exampleDir/src/hello/world/HelloWorld.groovy
exampleDir/bin/hello/world/HelloWorld.class
jars/groovy-all-2.0.1.jar
where:
(a) groovy-all-2.0.1.jar copied from my GROOVY_HOME/embeddable
(b) HelloWorld.groovy is compiled via groovyc and is as follows:
package hello.world
class HelloWorld {
public static void main(String[] args) {
println "Hello World!"
}
}
Just specifying sourceSets.main.runtimeClasspath as a classpath might not be enough. If you see NoClassDefFoundError this might help:
task( hello, dependsOn: jar, type: JavaExec ) {
main = 'hello.world.HelloWorld'
classpath(sourceSets.main.runtimeClasspath, sourceSets.main.compileClasspath)
}

Resources