For my Android project I want to run a test HTTP server for my integration tests. I've created a Configuration and have written a task to run my Groovy script the sets up the HTTP server
configurations {
stubs {
description = "Classpath for HTTP server for stubbed data"
visible = false
}
}
dependencies {
compile "com.android.support:support-v13:+"
stubs "org.codehaus.groovy:groovy:2.3.4"
stubs "com.github.tomakehurst:wiremock:1.46"
}
When I edit the Groovy script IntelliJ tells me that the Groovy SDK hasn't been configured.
How can I have IntelliJ use the Groovy SDK that is part of the stubs Configuration? I can't create a Groovy SDK configuration using the Gradle fetched libraries as IntelliJ tells me that the Groovy distribution is broken because the version number can't be determined.
Am I forced to have to download the distribution manually?
The solution was to separate out the project for the HTTP server into a separate project and use Gradle's multiproject's ability to set up the Android tests to depend on the HTTP server being started. Because the separate project is a Groovy project, IntelliJ reads the Groovy version to use from the project's dependencies and all is well.
dependencies {
compile "com.android.support:support-v13:+"
stubs project(":integration-server")
}
/*
* The android plugin defers creation of tasks in such a way that they can't be accessed eagerly as usual
* #see http://stackoverflow.com/questions/16853130/run-task-before-compilation-using-android-gradle-plugin
*/
gradle.projectsEvaluated {
connectedAndroidTest.dependsOn(":integration-server:startBackgroundServer")
// Note: finalizedBy is still #Incubating
connectedAndroidTest.finalizedBy(":integration-server:stopBackgroundServer")
}
integration-server/build.gradle
apply plugin: "groovy"
apply plugin: "spawn"
dependencies {
compile "org.codehaus.groovy:groovy:2.3.4"
compile "org.codehaus.groovy:groovy-ant:2.3.4"
compile "com.github.tomakehurst:wiremock:1.46"
}
task startBackgroundServer(type: SpawnProcessTask, dependsOn: "build") {
def cp = sourceSets.main.runtimeClasspath.asPath
command "java -cp $cp server"
ready "Started DelayableSocketConnector#0.0.0.0:8089"
}
task stopBackgroundServer(type: KillProcessTask)
To prevent the Gradle build blocking I'm using a Gradle Spawn Plugin to launch the HTTP server in the background.
Related
I am using karate 0.9.2 with gradle. My project requires to have all karate tests inside src/main/java. So I configured the gradle dependency as ‘compile’ instead of ‘testCompile’ and also modified the sourceSets to point to main instead of test. When I ran my runner class with above configuration I got empty test suite message.
build.gradle snippet:
compile 'com.intuit.karate:karate-junit4:0.9.3'
compile 'com.intuit.karate:karate-apache:0.9.3'
sourceSets {
test {
resources {
srcDir file('src/main/java')
exclude '**/*.java'
}
}
}
Additionally, I have is to run the karate tests from the deployable project jar. Please point me the resources I can refer to achieve the same.
Not something we directly support but teams have done this in Spring Boot etc. It should be possible, see if this thread helps: https://github.com/intuit/karate/issues/520
Also you may not need JUnit also: https://github.com/intuit/karate/issues/427
And see the sample project in this ticket as an example: https://github.com/intuit/karate/issues/529
EDIT - in 1.0 onwards we hope that class-loading from spring-boot JAR files is more reliable: https://github.com/intuit/karate/issues/751
I am using karate 0.9.2 with gradle. My project requires to have all karate tests inside src/main/java. So I configured the gradle dependency as ‘compile’ instead of ‘testCompile’ and also modified the sourceSets to point to main instead of test. When I ran my runner class with above configuration I got empty test suite message.
build.gradle snippet:
compile 'com.intuit.karate:karate-junit4:0.9.3'
compile 'com.intuit.karate:karate-apache:0.9.3'
sourceSets {
test {
resources {
srcDir file('src/main/java')
exclude '**/*.java'
}
}
}
Additionally, I have is to run the karate tests from the deployable project jar. Please point me the resources I can refer to achieve the same.
Not something we directly support but teams have done this in Spring Boot etc. It should be possible, see if this thread helps: https://github.com/intuit/karate/issues/520
Also you may not need JUnit also: https://github.com/intuit/karate/issues/427
And see the sample project in this ticket as an example: https://github.com/intuit/karate/issues/529
EDIT - in 1.0 onwards we hope that class-loading from spring-boot JAR files is more reliable: https://github.com/intuit/karate/issues/751
What I am trying to accomplish:
I want the tomcat 9 server to execute an automatic redeploy when I run a Gradle task that updates my HTML files.
This is my setup:
I use IntelliJ 2020.03 (ultimate edition), tomcat 9, the application is a GWT application.
My Configuration for Tomcat:
This is what I see when I hit the "Configure ..." button next to the line labeled "Application server:"
This is my Gradle task I run but tomcat does not automatically redeploy the changes
Things I already tried:
According to [https://www.jetbrains.com/help/idea/updating-applications-on-application-servers.html] I should have an option to "Update resources". But my options are limited to:
Therefore I assume I need to have "Exploded artifacts in local application server run configurations".
Therefore I headed to Tomcat -> Edit Configuration
I replaced the deploy to the exploded artifact:
Using this I get the following error message on starting up tomcat:
[2021-02-12 08:46:05,533] Artifact Gradle : NewComApp.war (exploded): com.intellij.javaee.oss.admin.jmx.JmxAdminException: com.intellij.execution.ExecutionException: C:\Users\heckner\IdeaProjects\NewComApp\build\libs\exploded\NewComApp.war not found for the web module.
So I decided to compare the artifact that "works" (but does not update the HTML files) with the "exploded" artifact which would be probably the right one but throws an error message on startup of tomcat.
This is the one which works ("NewComWar.war"):
This is the one which does throw an error message on startup ("NewComApp.war (exploded)":
As you can see in the image under "... which works". the war already seems to be "exploded". So why does IntelliJ does not offer the "update resources"?
But never the less, when I switch in Tomcat Edition to "NewCompApp.war (exploded)" i am able to select "update resources" in the drop down:
So probably this would be the way to go.
It obviously boils down to the point: What is wrong with the artifact declaration above so that tomcat throws the error message?
The feedback was: "ctually "NewComWar.war" is an archive that contains exploded artifact, that's why only "Redeploy" is possible. Please check that exploded artifact is created in "Output directory". "
Now the question is how I can add the exploded war to the Output Directory?
I tried:
but then I can only select from:
When I add this, it looks like this:
When I run Tomcat, it still says:
[2021-02-12 12:24:54,224] Artifact Gradle : NewComApp.war (exploded): com.intellij.javaee.oss.admin.jmx.JmxAdminException: com.intellij.execution.ExecutionException: C:\Users\heckner\IdeaProjects\NewComApp\build\libs\exploded\NewComApp.war not found for the web module.
Now I found the following tip (thanks Evgeny):
https://youtrack.jetbrains.com/issue/IDEA-178450#focus=streamItem-27-4068591.0-0
I switched under Settings -> Build, Execution, Deployment -> Build Tools -> Gradle: "Build and Run:" IntelliJ IDEA
I added this snipped to build.gradle:
task explodedWar(type: Copy) {
into "$buildDir/libs/exploded/${war.archiveFileName.get()}"
with war
}
war.dependsOn explodedWar
I switched the artifact which is deployed to the tomcat to
this automatically added the Gradle task:
Build 'Gradle:NewComApp.war (exploded) artifact to the
which is defined like this:
This accomplishes two things:
I can choose "Update resources" on my Edit Configuration for Tomcat like shown below:
My deployment runs well under tomcat
But ... :-)
Updates to the HTML files (within the war file) are not exploded to the NewComWar.war directory.
When I start tomcat I see the following file structure under C:\users<myname>\IdeaProjects\NewComApp\Libs\
The reason for this is that we use a Gradle task that generates the HTML files.
This task is called "copyHTML"
Under build.gradle it is defined now as follows:
war {
from 'war'
dependsOn copyHtml
exclude excludeInWar
doFirst {
manifest {
def version = ant.hasProperty('gitversion') ? ant.gitversion : 'undefined version'
println "Version: ${version}"
attributes("Implementation-Title": project.name, "Implementation-Version": version, "Built-By": new Date())
}
}
}
task explodedWar(type: Copy) {
into "$buildDir/libs/exploded/${war.archiveFileName.get()}"
with war
}
war.dependsOn explodedWar
copyHtml {
dependsOn generatorClasses
inputs.dir 'html'
inputs.dir 'email'
inputs.dir 'email.Tags'
inputs.dir props.getProperty('generator.htmlfiles.prefix') + 'html'
inputs.dir props.getProperty('generator.htmlfiles.prefix') + 'html.MeetingApp'
inputs.dir props.getProperty('generator.htmlfiles.prefix') + 'staticHtml'
inputs.properties props
outputs.dirs 'war', 'resources/com/newcomapp/server/mail'
doFirst {
ant.properties["generator.classpath"] = sourceSets.generator.runtimeClasspath.getAsPath()
}
}
task warWithoutGwt(type: War, dependsOn: war) {
}
gradle.taskGraph.whenReady { graph ->
if (graph.hasTask(warWithoutGwt)) {
compileGwt.enabled = false
}
}
When I run the Gradle task "warWithoutGWT" while tomcat still runs it says:
C:\Users<myname>\IdeaProjects\NewComApp\build\libs\exploded\NewComApp.war\WEB-INF\classes\com\newcomapp\server\integration\GeoLite2-Country.mmdb (The operation is not applicable to a file with an open area assigned to a user)
I assume that tomcat still holds a reference to that file, and the Gradle task tries to overwrite it (although there was no change to that file). Furthermore, I assume that this kills the rest of the Gradle task so that it does not update the HTML files (it's only an assumption though). How can I arrange an exploded war so that write-protected files are omitted and do not kill the rest of the Gradle task execution?
My answer up to now for this problem is: I changed the gradle script:
task explodedWar(type: Copy) {
into "$buildDir/libs/exploded/${war.archiveFileName.get()}"
exclude "**/*.mmdb"
with war
}
war.dependsOn explodedWar
so I added an "exclude for mmdb files". And this really works.
Is this a correct and good solution or do I overlook something? The reason I am asking is that changing HTML files in the scope of tomcat should be something very common with tomcat based projects. So I wonder if there is a more standardized, easier solution to this? It seems quite clumsy to copy and explode with additional gradle tasks the war file instead of IDEA take care of this.
When running a Cucumber test, using cucumber.api.cli.Main, the test is failing to recognise the certificates that are installed in the JDK.
I am running using the following:
IntelliJ 2016.1.2 (Build #IU-145.972)
JRE 1.8.0_74-b02
Plugin Cucumber for Java version: 999.999
It works, when run from the following gradle task, from the command line:
task functional(dependsOn: ['testClasses']) << {
javaexec {
main = "cucumber.api.cli.Main"
classpath = sourceSets.test.runtimeClasspath
args = ['--tags', '~#wip',
'--plugin', 'junit:build/junit-test-report.xml',
'--plugin', 'pretty',
'--plugin', 'html:build/cucumber-html-report',
'--plugin', 'json:build/cucumber-json-report.json',
'--glue', 'step_definitions',
'--strict',
'src/test/resources'
]
if(project.hasProperty("coverage")) {
jvmArgs = ["-javaagent:${configurations.codeCoverage.asPath}=destfile=${buildDir}/jacoco/jacoco.exec,sessionid=HSServ,append=false"]
}
}
}
But when I create a Run Configuration for Cucumber, using:
Main Class: cucumber.api.cli.Main
Glue: step_definitions
Feature or Folder path: /Users/xetius/application/src/test/resources/system_tasks/request/validation_handling/request/validate_hardware_fulfilment_request.feature
Program Arguments: --plugin org.jetbrains.plugins.cucumber.java.run.CucumberJvmSMFormatter --monochrome --name "^Pending details$"
Working Directory: /Users/xetius/application
It fails to recognise the certificates for connecting to the remote services.
I have configured IntelliJ to boot using the external JDK, into which I have installed the certificates using keytool, and I can see that it is using this JDK when running the configuration. I have also tried configuring Server Certificates, and importing the same certificate.
However, within IntelliJ, it throws an exception when connecting to remote services. It is also throwing the exception when gradle is run from within the IntelliJ terminal.
I'm using Gradle (Gradle 1.6 -upto 1.9) to build a Java project. Tried with both Java 1.6 or 1.7.
src/java - contains Java source code
test/java - contains test java code
Project compiles/builds successfully. During the build time, Junit UNIT test(s) runs successfully as well. I have only one test and it uses JMockit library. Please NOTE: This same jacoco code works fine in any other project where I don't have test which needs JMockit library.
JMockit groupid:artifactid:version is:
jmockit:jmockit:1.1
I wanted to have Jacoco code coverage enabled. Jacoco version that I have tried so far is shown in the code below, this code exists in my Gradle build script.
I added the following lines to my project's build.gradle file.
apply plugin: 'jacoco'
jacoco {
//toolVersion = "0.6.2.201302030002"
toolVersion = "0.7.0.201403182114"
//toolVersion = "0.7.1.201404171759" --- trying to find how to make version this working.
// reportsDir = file("$buildDir/customJacocoReportDir")
}
test {
ignoreFailures = true
testReportDir = file("$buildDir/reports/tests/UT")
testResultsDir = file("$buildDir/test-results/UT")
// Uncomment the following if you need more detailed output.
//testLogging.showStandardStreams = true
//onOutput { descriptor, event ->
// logger.lifecycle("Test: " + descriptor + " produced standard out/err: " + event.message )
//}
//Following Jacoco test section is required only in Jenkins instance extra common file
jacoco {
//The following vars works ONLY with 1.6 of Gradle
destPath = file("$buildDir/jacoco/UT/jacocoUT.exec")
classDumpPath = file("$buildDir/jacoco/UT/classpathdumps")
//Following vars works only with versions >= 1.7 version of Gradle
//destinationFile = file("$buildDir/jacoco/UT/jacocoUT.exec")
// classDumpFile = file("$buildDir/jacoco/UT/classpathdumps")
}
}
task integrationTest( type: Test) {
//Always run tests
outputs.upToDateWhen { false }
ignoreFailures = true
testClassesDir = sourceSets.integrationTest.output.classesDir
classpath = sourceSets.integrationTest.runtimeClasspath
testReportDir = file("$buildDir/reports/tests/IT")
testResultsDir = file("$buildDir/test-results/IT")
//Following Jacoco test section is required only in Jenkins instance extra common file
jacoco {
//This works with 1.6
destPath = file("$buildDir/jacoco/IT/jacocoIT.exec")
classDumpPath = file("$buildDir/jacoco/IT/classpathdumps")
//Following works only with versions >= 1.7 version of Gradle
//destinationFile = file("$buildDir/jacoco/IT/jacocoIT.exec")
// classDumpFile = file("$buildDir/jacoco/IT/classpathdumps")
}
}
jacocoTestReport {
group = "Reporting"
description = "Generate Jacoco coverage reports after running tests."
ignoreFailures = true
executionData = fileTree(dir: 'build/jacoco', include: '**/*.exec')
reports {
xml{
enabled true
//Following value is a file
destination "${buildDir}/reports/jacoco/xml/jacoco.xml"
}
csv.enabled false
html{
enabled true
//Following value is a folder
destination "${buildDir}/reports/jacoco/html"
}
}
//sourceDirectories = files(sourceSets.main.allJava.srcDirs)
sourceDirectories = files('src/java')
classDirectories = files('build/classes/main')
//------------------------------------------
//additionalSourceDirs = files('test/java')
//additionalSourceDirs += files('src/java-test')
//additionalClassDirs = files('build/classes/test')
//additionalClassDirs += files('build/classes/integrationTest')
//additionalClassDirs += files('build/classes/acceptanceTest')
//------------------------------------------
}
My questions:
1. When I'm not using "apply plugin: 'jacoco'", then :test task runs successfully (I have only one test). BUT, when I enable apply plugin: 'jacoco', then during :test task, I see the following line during build output and the process just hangs there and sits for hours and doesn't proceed.
Starting process 'Gradle Worker 1'. Working directory: /production/jenkinsAKS/workspace/MyProjectSvc Command: /production/jdk1.6.0_03/bin/java -Djava.security.manager=jarjar.org.gradle.processinternal.child.BootstrapSecurityManager -javaagent:build/tmp/expandedArchives/org.jacoco.agent-0.7.0.201403182114.jar_2kiqpmj1hlqbuth11j0qnuarhs/jacocoagent.jar=destfile=build/jacoco/UT/jacocoUT.execappend=true,dumponexit=true,output=file,classdumpdir=build/jacoco/UT/classpathdumps,jmx=false -Dfile.encoding=UTF-8 -ea -cp /production/jenkins/.gradle/caches/1.6/workerMain/gradle-worker.jar jarjar.rg.gradle.process.internal.launcher.GradleWorkerMain
An attempt to initialize for well behaving parent process finished.
Successfully started process 'Gradle Worker 1'
Gradle Worker 1 executing tests.
> Building > :test
I googled around and it seems like there's some incompatibility between Jacoco and JMockit libraries in the current latest version and there's a fix coming to get this issue resolved. The new version of Jacoco 0.7.1.xxxxx has the fix but I don't know when it'll be available in Maven repository.
Any idea, how can I set the javaagent to ignore the test/test class file for JACOCO and still apply jacoco plugin. In my case, apply plugin: 'jacoco' will later exist in a global file i.e. inside /init.d/global-common.gradle file within allProjects { .... } section.
I tried the following but still, the build process hangs at :test task until I uncomment exclude below. If I comment out the whole jacoco subsection within test section, build process still hangs at :test task (seems like as apply plugin: 'jacoco' is there). If I uncomment exlude, then I don't see error but then no test runs i.e. index.html for test reports shows nothing ran.
test {
include "**/*"
jacoco {
//exclude "**/util/Test*"
}
}
2. How can I use the jacoco 0.7.1.xxxx version (non-release aka nightly release which has the fix for this issue) in my build.gradle file. When I used 0.7.1.xxx version after uncommenting it (as shown above), it errored out saying can't find dependency jacoco:0.7.1.xxxx
3. To get rid of this issue, I think I can set a jacoco agent parameter i.e. when it runs, it'll ignore the JMOckit/JUnit .jar library or something. See/Found the following links:
http://javaee.ch/2012/10/09/jmockit-with-maven-sonar-jacoco-and-jenkinshudson/
https://github.com/jacoco/jacoco/pull/35
Acc. to the second link:
A workaround which avoids the problem is to exclude the JUnit classes from JaCoCo's consideration. I used the following JVM initialization parameter in my testing, excluding both JUnit and TestNG classes: -javaagent:/jacoco-0.7.1/lib/jacocoagent.jar=excludes=junit.:org.junit.:org.testng.
The good news is that the fix I described in my previous comment also solves this deadlock problem, because then the JUnit classes will be ignored by JaCoCo as they get instrumented by JMockit.
I'm trying to find what variable in jacoco { ... } or within test { ... } I can set to do the same until I get the new version of Jacoco or JMockit (which has the fix). Seems like it's within test section i.e. test { ..here jvmArgs '...'will be set. jacoco { ... } .. }
http://stevendick.github.io/blog/2012/01/22/jacoco-and-gradle/
4. If I exclude the test class file by using "exclude "com/xxx/yyy/a/b/c/util/Testname.class", then it works and I don't see an error but then I found that due the this exclude, my test never run!!!
that's why it didn't hang. Well, I want the test to run and don't want Jacoco to process it.
Just by having apply plugin: 'jacoco' in build.gradle is hanging the build at :test task. I need jacoco as Development team would like to see the code coverage details as well.
At this time, I'm trying to find answers to the above ?s, appreciate your inputs.
Final answer:
Both Jmockit and Jacoco instruments the class files. Jmockit does it first during the build process and when jacoco tries the same (later in the process) it says "oh oh, can't instrument an already instrumented class file". This issue happened with older versions of jacoco and jmockit. To see this error, enable --stacktrace option during Gradle build or --debug.
Now, using the latest jacoco and jmockit versions, we can solve this issue easily.
If you use jacoco:
toolVersion="0.7.1.201405082137"
or
toolVersion="0.7.2.201409121644"
See this: changes that went in 0.7.1 version
http://www.eclemma.org/jacoco/trunk/doc/changes.html
For JMockit, you have to use jmockit version: 1.8 at least or later (1.9 to 1.13).
org.jmockit:jmockit:1.8
See this: changes that went under 1.8 version: http://jmockit.github.io/changes.html
Answer 1: Setting jacoco subsection (within test section) -- enabled field to "false" did the trick. I'm not getting the code coverage (which I can live with until I get the new versions out for both JMockit / Jacoco) but now I see valid test report index.html file (i.e. test ran successfully) and still apply plugin: 'jacoco' can stay effective in /init.d/global-common.gradle file ...
test {
jacoco {
enabled false
}
}
For Answer 2: NOT found so far, will share.
Answer 3: Didn't resolve the error - but how you set it up is given at the link: http://stevendick.github.io/blog/2012/01/22/jacoco-and-gradle/
I tried giving, may be I didn't use it correctly. jvmArgs '....: ,....:.. ,....:....,exclude="com.:org.gradle.;jmockit.:mockit.:junit.*"
Answer 4: Answer 1 will suffice.
I'm not too familiar with gradle, so I'm not sure I can help with questions 1, 3, or 4...
But question 2, I can help - the version string for JaCoCo 0.7.1 is not 0.7.1.201404171759 but rather 0.7.1.201405082137. This version has been formally released, in case you hadn't noticed.
If you want the latest nightly build, the convention is to simply refer as 0.7.2-SNAPSHOT (make sure you are pointing at the snapshot repository at https://oss.sonatype.org/content/repositories/snapshots/).