Cucumber-JVM with Gradle, how to run tests automatically - gradle

I'm working on a Java project that uses Gradle as its build system.
I want to add some bdd tests using Cucumber-JVM. Following this example I was able to configure Gradle's build.gradle to have a task called cucumber, and I was able to execute that task using "gradle cucumber".
But what I am looking for is a way to have Gradle run that task automatically during its test phase (where it runs all the other regular unit tests). I also want the build to be flagged as failed if any of the cucumber tests fail (strict=true).
Is this possible? I don't know a lot about Gradle and Google so far has produced nothing really useful.

Okay so I figured out how to achieve this. Simply add this to build.gradle:
test << {
javaexec {
main = "cucumber.api.cli.Main"
classpath = configurations.cucumberRuntime + sourceSets.main.output + sourceSets.test.output
args = ['--strict', '--monochrome', '--plugin', 'pretty', '--glue', 'com.mypackage', 'src/test/resources']
}
}
All you really need are the feature file and the steps java files that implement the glue code. You do not need the xxxCukesTest.java file with a #RunWith annotation since Gradle ignores it. You may want to keep it anyway because it enables you to run tests from your IDE.
Works really neat!

Related

How can I share build code script for all my gradle projects (not just subprojects)

I want to have this code snippet
test {
testLogging.showStandardStreams = true
}
Shared for all my gradle projects. Is that possible? Preferrably something I add to ~/.gradle/common.gradle or similar.
Probably the best way to inject build logic into existing build scripts without touching them is using init scripts. So you can create a script like testlogging.gradle that looks like this:
allprojects {
tasks.withType(Test) {
testLogging.showStandardStreams = true
}
}
As you can see I use tasks.withType(Test) instead of test here to reference the test task by type. That has some benefits:
this script works also for builds with no task with name test. This could likely happen (e.g. in multiproject builds)
this script would also apply for any other tasks in your build that are of type Test. Some projects use integTest etc.
To auto apply this script on your machine, you can put it in the folder ~/.gradle/init.d. Gradle considers every .gradle file in there as init script and applies them to each build.
To learn more details about init scripts check the according chapter in the gradle userguide.

How to use Gretty integrationTestTask with a war file?

Is it possible to use gretty integrationTestTask with a project that uses a war folder?
It seems from the documentation appBeforeIntegrationTest does not have access to the war. Is there another way to run test cases so that it uses the war folder?
Ideally, I want jettyStart -> test -> jettyStop to run. Although when I run it straight jettyStart hangs indefinitely, until jettyStop is run. Is there a way to run jettyStart in Gradle in the background or something?
Regardless what file structure your application has, the integrationTestTask is supposed to be configured with the name of an exsiting gradle task to execute when gradle integrationTest is run:
gretty {
// ...
integrationTestTask = 'integrationTest' // name of existing gradle task
// ...
}
What you want to archive is this:
gretty {
integrationTestTask = 'test'
}
Gretty's workflow when calling integrationTest is as follows:

How to pass system properties to the tests in gradle in the smart way?

build.gradle
tasks.withType(Test){
systemProperties=System.properties
println systemProperties['param']
}
Now I can either pass parameters in the command line:
gradle test -Dparam=10
or put them in gradle.properties:
systemProp.param=15
Ideally I would like to put the defaults in the gradle.properties, and be able to overwrite them from the command line. Unfortunately if I do that, the gradle.properties has precedence, and -Dparam=10 is ignored.
Could you offer any solutions on that?
https://issues.gradle.org/browse/GRADLE-2122
It works since 2.12 or 2.13 "the smart way" already!
The example above is working, the command line -D option overdrives the defaults in gradle.properties
I am using gradle 2.12 and sharing how I used it:
test {
// support passing -Dsystem.property=value to bootRun task
systemProperties = System.properties
}
I have JUnit tests that I wanted to skip unless a property was used to include such tests. Using JUnit Assume for including the tests conditionally:
//first line of test
assumeThat(Boolean.parseBoolean(System.getProperty("deep.test.run","false"),true)
Doing this with gradle required that the system property provided at the time of running gradle build, shown here,
gradle build -Ddeep.test.run=true
was indeed passed through to the tests.
Hope this helps others trying out this approach for running tests conditionally.

Gradle: Fail on adding systemProperty

I'm trying to add a .dll file to the "java.library.path" system property via gradle on my Spring Boot project. I'm using Gradle 2.1 on STS.
This is the small piece of groove code within my build.gradle:
tasks.withType(JavaCompile) {
systemProperty "java.library.path", file("./src/main/resources/META-INF/opencv-2.4.9/windows_bin/x64")
}
And I'm getting the following error:
Could not find method systemProperty() for arguments [java.library.path, D:\GitHub\TFG_1\GuiaTV\src\main\resources\META-INF\opencv-2.4.9\windows_bin\x64] on root project 'GuiaTV'
That path does exists, so I don't know where the problem is.
Any help? Thank you!
UPDATE 1:
#Amnon Shochot
What I try to do is to add a native library (.dll) to the project. I took the idea from some sites (for example, http://zouxifeng.github.io/2014/07/17/add-system-property-to-spring-boot.html, https://github.com/cjstehno/coffeaelectronica/wiki/Going-Native-with-Gradle).
The first one is using what you suggested:
tasks.withType(JavaExec) {
systemProperty "java.library.path", file("./libs")
}
The second one is using:
run {
systemProperty 'java.library.path', file( 'build/natives/windows' )
}
None of them are working for me.
The first one (with JavaExec) is failing gradle test throwing:
java.lang.UnsatisfiedLinkError: no opencv_java249 in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1865)
at java.lang.Runtime.loadLibrary0(Runtime.java:870)
If you follow the trace, it's crashing at runtime in sentence: System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
And the second one is failing on gradle build with the following message:
Could not find method run() for arguments [build_24sfpo0st6dokeq7fn3ad7r34$_run_closure7#2652c3da] on root project 'GuiaTV'.
Luckily you know exactly what I try to achieve and you can solve my problem.
Thank you for your interest!
UPDATE 2:
Finally, I ended up adding these lines to my build.gradle script:
// The following makes "gradle build", "gradle test" work
test {
jvmArgs = ['-Djava.library.path=./src/main/resources/META-INF/opencv-2.4.9/windows_bin/x64']
}
// Thw following makes "gradle run" work
run {
jvmArgs = ['-Djava.library.path=./src/main/resources/META-INF/opencv-2.4.9/windows_bin/x64']
}
By the way, I'm also using "spring-boot" gradle plugin. That's where the run task comes from.
So, I can execute "gradle build", "gradle test" and "gradle run" sucessfully. This is, that native library is correctly added.
However, since I'm also using "eclipse" gradle plugin, I would like to add the native library simply by executing "gradle eclipse". Instead, I must create the library on Eclipse manually, and add it to my project.
Thank you #Amnon for your collaboration. I'll be posting a new solution in the case I found it.
The problem is that you do not set the context for the systemProperty method thus Gradle tries to locate it in the project object where it does not exist which is the reason for the error you got.
If you wanted to apply this configuration for all tasks of type JavaCompile your code should have been looked like:
tasks.withType(JavaCompile) { JavaCompile t ->
t.systemProperty "java.library.path", file("./src/main/resources/META-INF/opencv-2.4.9/windows_bin/x64")
}
However, the JavaCompile task type also does not contain a systemProperty so this code wouldn't work either.
You can define CompileOptions for a JavaCompile task using its options property, i.e.:
tasks.withType(JavaCompile) { JavaCompile t ->
t.options "java.library.path", file("./src/main/resources/META-INF/opencv-2.4.9/windows_bin/x64")
}
However, I'm not sure whether you can define this specific system property.
One last note - the systemProperty method does exist for tasks of type JavaExec in case that this is what you intended to do.

Gradle - Add additional task to existing task

I'm working on a project that uses EJB2s. The created EJB Jars require additional processing by the application server before they're bundled in the war/ear and deployed.
I have created a custom task that works to do the additional processing if I invoke it explicitly (gradle ejbDeploy), but am having trouble fitting it into the gradle multi-project lifecyle. I need to somehow add it to the build graph to execute automatically after the jar task.
My first attempt was to add it to jar with
jar.doLast{
ejbDeploy.execute()
}
which seems to work for arbitrary code blocks, but not for tasks
What's the recommended solution for this? I see three approaches:
Hook into the build graph and add it explicitly after the jar
task.
Set it up somehow in jar.doLast{}
Set it up as a prerequisite for the WAR task execution
Is there a recommended approach?
Thanks!
I would go for approach #3 and set it up as a dependency of the war task, e.g.:
war {
it.dependsOn ejbDeploy
...
}
I'm new to Gradle, but I would say the answer really depends on what you're trying to accomplish.
If you want to task to execute when someone runs the command gradle jar, then approach #3 won't be sufficient.
Here's what I did for something similar
classes {
doLast {
buildValdrConstraints.execute()
}
}
task buildValdrConstraints(type: JavaExec) {
main = 'com.github.valdr.cli.ValdrBeanValidation'
classpath = sourceSets.main.runtimeClasspath
args '-cf',valdrResourcePath + '/valdr-bean-validation.json'
}
Add the following, and then ejbDeploy will be executed right after jar, but before war
jar.finalizedBy ejbDeploy
See Gradle Docs. 18.11. Finalizer tasks

Resources