Gradle does not import groovy class when running task - gradle

I have a gradle (1.8) project with 2 classes A and B where B import A. Both files are under /foo/bar/ package (myProjectFolder/test/foo/bar folder).
A.groovy class
package foo.bar
import org.junit.Test;
public class ATest{
#Test
public void run() {
System.out.println("CLASS A");
}
}
B.groovy class
package foo.bar
import org.junit.Test;
public class BTest{
#Test
public void run() {
ATest a = new ATest();
a.run();
System.out.println("CLASS B");
}
}
build.gradle
apply plugin: "groovy"
apply plugin: "java"
repositories {
mavenCentral()
}
dependencies {
groovy group: "org.codehaus.groovy", name:"groovy-all", version: "1.8.6"
testCompile "junit:junit:4.10"
}
test {
testLogging.showStandardStreams = true
}
sourceSets {
test { groovy {
srcDir 'test/foo/bar'
} }
}
buildscript {
repositories { mavenCentral() }
}
configurations{
addToClassLoader
}
dependencies {
addToClassLoader "junit:junit:4.10"
}
URLClassLoader loader = GroovyObject.class.classLoader
configurations.addToClassLoader.each {File file ->
loader.addURL(file.toURL())
}
task runA << {
new GroovyShell().run(file('test/foo/bar/ATest.groovy'));
}
task runB << {
new GroovyShell().run(file('test/foo/bar/BTest.groovy'));
}
Output console for gradle clean -Dtest.single=A test
[root#vm1]# gradle clean -Dtest.single=A test
The groovy configuration has been deprecated and is scheduled to be removed in Gradle 2.0. Typically, usages of 'groovy' can simply be replaced with 'compile'. In some cases, it may be necessary to additionally configure the 'groovyClasspath' property of GroovyCompile and Groovydoc tasks.
:clean
:compileJava UP-TO-DATE
:compileGroovy UP-TO-DATE
:processResources
:classes
:compileTestJava UP-TO-DATE
:compileTestGroovy
:processTestResources UP-TO-DATE
:testClasses
:test
foo.bar.ATest > run STANDARD_OUT
CLASS A
BUILD SUCCESSFUL
Total time: 13.205 secs
Output console for gradle clean -Dtest.single=B test
[root#vm1]# gradle clean -Dtest.single=B test
The groovy configuration has been deprecated and is scheduled to be removed in Gradle 2.0. Typically, usages of 'groovy' can simply be replaced with 'compile'. In some cases, it may be necessary to additionally configure the 'groovyClasspath' property of GroovyCompile and Groovydoc tasks.
:clean
:compileJava UP-TO-DATE
:compileGroovy UP-TO-DATE
:processResources
:classes
:compileTestJava UP-TO-DATE
:compileTestGroovy
:processTestResources UP-TO-DATE
:testClasses
:test
foo.bar.BTest > run STANDARD_OUT
CLASS A
CLASS B
BUILD SUCCESSFUL
Total time: 12.218 secs
Output console for gradle -q runA -i
[root#vm1]# gradle -q runA -i
Starting Build
Settings evaluated using empty settings script.
Projects loaded. Root project using build file '/opt/myProject/build.gradle'.
Included projects: [root project 'myProject']
Evaluating root project 'myProject' using build file '/opt/myProject/build.gradle'.
Starting file lock listener thread.
The groovy configuration has been deprecated and is scheduled to be removed in Gradle 2.0. Typically, usages of 'groovy' can simply be replaced with 'compile'. In some cases, it may be necessary to additionally configure the 'groovyClasspath' property of GroovyCompile and Groovydoc tasks.
All projects evaluated.
Selected primary task 'runA'
Tasks to be executed: [task ':runA']
:runA (Thread[main,5,main]) started.
:runA
Executing task ':runA' (up-to-date check took 0.001 secs) due to:
Task has not declared any outputs.
CLASS A
JUnit 4 Runner, Tests: 1, Failures: 0, Time: 63
:runA (Thread[main,5,main]) completed. Took 0.739 secs.
BUILD SUCCESSFUL
Total time: 7.826 secs
Output console for gradle -q runB -i <-- THIS EXECUTION FAILS and I don't know why.
[root#vm1]# gradle -q runB -i
Starting Build
Settings evaluated using empty settings script.
Projects loaded. Root project using build file '/opt/myProject/build.gradle'.
Included projects: [root project 'myProject']
Evaluating root project 'myProject' using build file '/opt/myProject/build.gradle'.
Starting file lock listener thread.
The groovy configuration has been deprecated and is scheduled to be removed in Gradle 2.0. Typically, usages of 'groovy' can simply be replaced with 'compile'. In some cases, it may be necessary to additionally configure the 'groovyClasspath' property of GroovyCompile and Groovydoc tasks.
All projects evaluated.
Selected primary task 'runB'
Tasks to be executed: [task ':runB']
:runB (Thread[main,5,main]) started.
:runB
Executing task ':runB' (up-to-date check took 0.001 secs) due to:
Task has not declared any outputs.
:runB FAILED
:runB (Thread[main,5,main]) completed. Took 0.237 secs.
FAILURE: Build failed with an exception.
* Where:
Build file '/opt/myProject/build.gradle' line: 46
* What went wrong:
Execution failed for task ':runB'.
> startup failed:
/opt/myProject/test/foo/bar/BTest.groovy: 8: unable to resolve class ATest
# line 8, column 9.
ATest a = new ATest();
^
/opt/myProject/test/foo/bar/BTest.groovy: 8: unable to resolve class ATest
# line 8, column 13.
ATest a = new ATest();
^
2 errors
* Try:
Run with --stacktrace option to get the stack trace. Run with --debug option to get more log output.
BUILD FAILED
Total time: 7.872 secs
So, what am I missing to run the task runB correctly?

Note: the premise of the question is based on a truly unorthodox use-case, which should be corrected. That said, I can explain the behaviour that is observed.
When the command-line specifies the test task, then ~/build/classes/test is added to the classpath. In the case of running the runB task, it is not. So BTest.groovy can't find ATest.
To correct it (only as an illustration, not as a suggestion for 'real' code), consider:
// don't do this in a real project!
task runB(dependsOn: 'compileTestGroovy') << {
def testDirURL = new File("${projectDir}/build/classes/test").toURL()
loader.addURL(testDirURL)
new GroovyShell(loader).run(file('test/foo/bar/BTest.groovy'))
}
Now, runB requires that the Groovy test code is compiled, and then manually (!?) adds it to the classloader used by GroovyShell.

Related

Cannot run cucumber JUnit tests on Gradle

I am trying to run a Cucumber / Selenium project using IntelliJ Community edition and Gradle 5.5.1.
My folder structure is as follows:
ProjectRoot
|
src---main---java
|
src---test---java---packagename---stepdefinitions---Steps.java
|
-----resources---feature---application.feature
My TestRunner class is as follows:
#RunWith(Cucumber.class)
#CucumberOptions(
plugin = {"pretty", "json:cucumber-report.json"},
features = {"src/test/resources/feature"})
public class TestRunner {
}
When I try to run the TestRunner what I get is the following:
Testing started at 18:48 ...
> Task :cleanTest
> Task :compileJava UP-TO-DATE
> Task :processResources NO-SOURCE
> Task :classes UP-TO-DATE
> Task :compileTestJava
> Task :processTestResources UP-TO-DATE
> Task :testClasses
> Task :test FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':test'.
> No tests found for given includes: [org.fifthgen.scanmaltatesting.TestRunner](filter.includeTestsMatching)
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 1s
5 actionable tasks: 3 executed, 2 up-to-date
This is my build.gradle:
plugins {
id 'java'
}
group 'org.fifthgen'
version '1'
sourceCompatibility = 11
targetCompatibility = 11
repositories {
mavenCentral()
}
wrapper.gradleVersion = '5.5.1'
def cucumberVersion = '4.7.2'
def junitVersion = '5.5.2'
dependencies {
implementation 'org.seleniumhq.selenium:selenium-java:3.141.59'
testImplementation "io.cucumber:cucumber-java:${cucumberVersion}"
testImplementation "io.cucumber:cucumber-junit:${cucumberVersion}"
testImplementation "org.junit.jupiter:junit-jupiter-api:${junitVersion}"
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${junitVersion}"
}
test {
useJUnitPlatform()
scanForTestClasses = false
}
When I run the test task using Gradle, I get
BUILD SUCCESSFUL in 0s
4 actionable tasks: 1 executed, 3 up-to-date
18:52:41: Task execution finished 'test'.
Without the Cucumber scenarios being run.
ˋRunWithˋ is a JUnit 4 mechanism. In order to use that with JUnit 5 platform mechanism you must include dependency on junit-vintage engine which allows running JUnit 4 tests on JUnit 5.
Alternatively you could change to the Cucumber engine for JUnit 5. I’m not sure though if it has already been released.
From the docs,
Cucumber is based on JUnit 4. If you’re using JUnit 5, remember to include junit-vintage-engine dependency, as well. For more information, please refer to JUnit 5 documentation.
Adding following dependencies made it work on IntelliJ:
testRuntimeOnly("org.junit.platform:junit-platform-launcher:1.7.2")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.7.2")
testRuntimeOnly("org.junit.vintage:junit-vintage-engine:5.7.2")
Check here for more details

Trying to run Spock Specification using Gradle... "Test Events were not received" (In IntelliJ Idea)

I am trying to run a simple Spock specification with Groovy, in a Gradle project. But I am getting this message Test events were not received.
Here is my build.gradle:
plugins {
id 'groovy'
}
group 'com.Sample'
version '1.0-SNAPSHOT'
apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'groovy'
repositories {
mavenCentral()
}
dependencies {
compile 'org.codehaus.groovy:groovy-all:2.3.11'
testCompile "org.spockframework:spock-core:1.1-groovy-2.4"
}
Here is my spock specification :
import spock.lang.Specification
class SampleSpec extends Specification {
def "validate string concat"(){
given:
def string1 = "hello"
def string2 = "world"
when:
def stringConcat = string1.concat(string2)
then:
stringConcat == "helloworld"
}
}
Here is the message I get when I run the Spock Specification:
> Task :cleanTest UP-TO-DATE
> Task :compileJava UP-TO-DATE
> Task :compileGroovy NO-SOURCE
> Task :processResources NO-SOURCE
> Task :classes UP-TO-DATE
> Task :compileTestJava NO-SOURCE
> Task :compileTestGroovy NO-SOURCE
> Task :processTestResources NO-SOURCE
> Task :testClasses UP-TO-DATE
> Task :test NO-SOURCE
BUILD SUCCESSFUL in 0s
2 actionable tasks: 2 up-to-date
9:20:33 AM: Tasks execution finished ':cleanTest :test --tests "SampleSpec.validate string concat"'.
Any help would be greatly appreciated!
EDIT:
Now my Spock tests are running successfully but I am getting this message:
WARNING: Illegal reflective access by org.codehaus.groovy.reflection.CachedClass (file:/C:/Users/dtara/.gradle/caches/modules-2/files-2.1/org.codehaus.groovy/groovy-all/2.4.9/3334e99a8baae12d6e014d444149e337ceb99a00/groovy-all-2.4.9.jar) to method java.lang.Object.finalize()
WARNING: Please consider reporting this to the maintainers of org.codehaus.groovy.reflection.CachedClass
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
**Anyone knows that this means? Should I worry about it? **
Ok, first question:
The tests should live in src/test/groovy not src/test/java (and packages would be nice) ;-)
Second question:
You're using quite an old version of Groovy, but until Groovy 3.0 comes out, you'll see that warning when using Java 9+. It's trying to use things in Java that Java is going to remove in a future release...
It's fine to run with what you have at the moment (apart from maybe pull in the latest groovy -- 2.5.8 at the time I'm writing this)

How to build a WAR file with gradle?

I want to build a WAR file (and then deploy it to Tomcat). So, as an exercise, I've started a new Spring Boot Project using Gradle in IDEA IntelliJ. Afterwards, I've apply the plugin in the build.gradle file, like this apply plugin: 'war'
.
The problem is that when I try to run gradle war in the terminal, I get no war file! The only thing that happens is that it will generate a \build with 3 subsolders classes, resources and tmp, but there's no WAR in these.
What should I do to get a WAR file? I've watched this video, but this guy uses Maven and doesn't do advanced stuff and gets the war. I think there's got to be a way to keep it simple.
When I run gradle war --info
Initialized native services in: C:\Users\...\.gradle\native The client
...
Task :compileJava UP-TO-DATE
Resolving global dependency management for project 'deleteme'
Excluding [org.apache.tomcat:tomcat-annotations-api]
Excluding []
Skipping task ':compileJava' as it is up-to-date.
:compileJava (Thread[Task worker for ':',5,main]) completed. Took 0.753 secs.
:processResources (Thread[Task worker for ':',5,main]) started.
Task :processResources UP-TO-DATE
Skipping task ':processResources' as it is up-to-date.
:processResources (Thread[Task worker for ':',5,main]) completed. Took 0.003 secs.
:classes (Thread[Task worker for ':',5,main]) started.
Task :classes UP-TO-DATE
Skipping task ':classes' as it has no actions.
:classes (Thread[Task worker for ':',5,main]) completed. Took 0.0 secs.
:war (Thread[Task worker for ':',5,main]) started.
Task :war SKIPPED
Skipping task ':war' as task onlyIf is false.
:war (Thread[Task worker for ':',5,main]) completed. Took 0.0 secs.
I guess that you have applied the spring boot gradle plugin to your project, in addition to the war plugin ? then this behaviour is normal, since the Spring Boot plugin will disable jar and war tasks and replace these with bootWar and bootJar tasks .
With both spring boot and war plugin applied:
./gradlew war
15:35:09: Executing task 'war'...
> Task :compileJava UP-TO-DATE
> Task :processResources UP-TO-DATE
> Task :classes UP-TO-DATE
> Task :war SKIPPED
BUILD SUCCESSFUL in 0s
2 actionable tasks: 2 up-to-date
15:35:10: Task execution finished 'war'.
Note the SKIPPED message
$ ./gradlew bootWar
15:36:35: Executing task 'bootWar'...
> Task :compileJava UP-TO-DATE
> Task :processResources UP-TO-DATE
> Task :classes UP-TO-DATE
> Task :bootWar
BUILD SUCCESSFUL in 1s
3 actionable tasks: 1 executed, 2 up-to-date
15:36:37: Task execution finished 'bootWar'.
Then you will get the expected war file under build/libs.
You can still re-enable the standard jar/war tasks as explained here : https://docs.spring.io/spring-boot/docs/current/gradle-plugin/reference/html/#packaging-executable-wars-deployable (if you need to produce normal archives and not executable archives)
Regarding the Tomcat issue: install Tomcat 8.5.
Please read: https://docs.gradle.org/current/userguide/war_plugin.html
If using Gradle with IntelliJ, goto build.gradle (or build.gradle.kts for Kotlin) and add
id 'war'
(or just
war
for Kotlin ) under Plugins
Reload Gradle Project and then use gradlew bootWar on the Intellij Terminal.
Add --info or --stackTrace for debugging
As rightly said by #M.Ricciuti, the spring boot gradle plugin will disable the jar/war tasks and would only work with bootJar/bootWar tasks. But if you still want your project to be packaged with jar/war tasks just add the below to your build.gradle file
war {
enabled=true
}
This would enable the gradle war command to generate the war for your project.
I was also facing the same issue.
After a lot of struggle, I figured out that I needed to extend SpringBootServletInitializer in my application. So my effective code looks like
public class SyncApplication extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(SyncApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(SyncApplication.class, args);
}
}
Looks like this SpringBootServletInitializer directs war plugins generate bootstrapping code while building the war, and thus spring context is initialized while deploying the app.
If you are using spring boot with gradle, you should follow the steps below:
Edit your build.gradle file adding apply plugin:'war' and then rebuild gradle.
With gradle built two (2) files will be created on your root directory:
gradlew (for Linux) and gradlew.bat (for windows)
Open your terminal on your current project and run
./gradlew war
Your project will build and generate a .war file in build/libs/

How to run JavaExec with out compile

I run a gradle javaexec in build.gradle
task main(type: JavaExec) {
main = 'com.gtan.Application'
classpath = sourceSets.main.runtimeClasspath
}
this is the output result:
:compileJava UP-TO-DATE
:compileScala UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:main
i want run this javaexec without compile tasks. like:
:main
what should i do ?
When you set up the classpath as the runtime classpath from the main sourceSet, you're telling Gradle that your task depends on the output from the main sourceSet. So, it will compile the main source set first, in order to ensure that the classpath is correctly set up for your JavaExec task.
The answer to your question depends on where the com.gtan.Application class is, and what classpath the application is expecting. If this class resides in the local project, under src/main/java, you won't be able to get rid of compilation, because Gradle must compile this class in order to execute it.
If the class lives in a JAR that your build depends on, for example:
dependencies {
runtime 'com.gtan:this-example-has-what-to-run:1.0.0'
}
Then, you can change your task definition to:
task main(type: JavaExec) {
main = 'com.gtan.Application'
classpath = configurations.runtime
}
By setting the classpath to a configuration, Gradle does not need to perform any compilation, and you get:
$ ./gradlew main
:main

Is there a way to have Gradle call flywayMigrate on build?

I'd find it really useful to invoke Flyway's migrate command automatically each time I run gradle build.
Spring Boot does this under the hood, but can Gradle do this itself? I have a non-Boot app that I'd like to be able to manage the same way.
I'm hoping it is some lifecycle hook. This question is helpful, but how do I execute flyway pre-build?
Yes you can. You have several options. You can hook into the lifecycle at any point. By default the java gradle plugin has several places you could hook into.
$ ./gradlew clean build
:clean
:compileJava
:processResources UP-TO-DATE
:classes
:jar
:assemble
:compileTestJava
:processTestResources UP-TO-DATE
:testClasses
:test
:check
:build
You can attach to any of these points
Or you if you need to be applied no matter what before anything else then you might want to consider a simple plugin.
Here is an example of both:
build.gradle:
apply plugin: 'java'
repositories {
jcenter()
}
dependencies {
testCompile 'junit:junit:4.12'
}
task runFlyAwayCommand << {
// process is type java.lang.Process
def process = "printf lifecycle hooked task".execute()
def processExitValue = process.waitFor()
def processOutput = process.text
project.logger.lifecycle("Flyaway{ exitValue: $processExitValue output: $processOutput }")
}
// compileJava could be any lifecycle task
tasks.findByName('compileJava').dependsOn tasks.findByName('runFlyAwayCommand')
// if you need to execute earlier you might want to create a plugin
apply plugin: SamplePlugin
class SamplePlugin implements Plugin<Project> {
#Override
void apply(Project project) {
def process = "printf plugin apply".execute()
def processExitValue = process.waitFor()
def processOutput = process.text
project.logger.lifecycle("Flyaway{ exitValue: $processExitValue output: $processOutput }")
}
}
Output:
$ ./gradlew clean build
Configuration on demand is an incubating feature.
Flyaway{ exitValue: 1 output: plugin }
:clean
:runFlyAwayCommand
Flyaway{ exitValue: 1 output: lifecycle }
:compileJava
:processResources UP-TO-DATE
:classes
:jar
:assemble
:compileTestJava
:processTestResources UP-TO-DATE
:testClasses
:test
:check
:build
BUILD SUCCESSFUL
Total time: 1.294 secs

Resources