Specifying xmlpathinjar TestNG option with Gradle test task - gradle

Is it possible to run a TestNG test suite that is embedded in a JAR file via a Gradle test task?
My project includes JARed bundles of TestNG tests that have an embedded testng.xml file defining which tests should be run in the JAR. Is it possible for Gradle to refer to this embedded XML when running the TestNG tests?
From the command line I use the xmlpathinjar option.

I dont think it can be done using the Gradle TestNG task. I couldn't find any such support in the TestNGOptions
Instead of using
test{
useTestNG()
}
you could try going through this post on SO How can I tell Gradle to use my testng.xml file for Test Classes and Ordering? and maybe employ the approach detailed here https://stackoverflow.com/a/28868416
But when you are using a custom Gradle task to run your TestNG tests, please make sure that you add a reference to the ExitCodeListener
Here's a sample
task ('myTask', type: JavaExec) {
main = 'org.testng.TestNG'
classpath = sourceSets.main.runtimeClasspath + sourceSets.test.runtimeClasspath
args = ["-xmlpathinjar", "suites/mysuite.xml", "-listener", "org.testng.TestNG\$ExitCodeListener"]
}
More details on why the ExitCodeListener needs to be referred, can be found here

Related

calling Karate framework from Rest service or spring boot [duplicate]

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

In a multi-module project can Gradle build a plugin as one module and then use that plugin in the same build?

We have a Gradle project with a bunch of modules. One of those modules is a custom code generator, written as a Gradle plugin. We want to run that code-generator plugin in another module later in the same overall multi-module build, in order to test the code generator.
We know how to create a separate project on the fly and run the code generator in that, but we need to run the code generator in the main project, not in a temporary test project.
Nothing we have tried works, and the Gradle documentation doesn't appear to address this. It seems to be fundamental to Gradle's design, because the entire set of plugins used in a build is basically a single program, assembled at the start. Trying to add a just-now-built plugin after the fact seems unsupported, or we're missing something.
The best we've been able to come up with so far is to implement the plugin in Java (Kotlin would also have worked), so the Gradle plugin is just a thin Gradle skin over the implementation, and call the Java implementation directly when running the code generator in the other module. This works, but it means we aren't actually testing the Gradle portion of the code generator.
This is natively supported in Maven (maven multi-module project with one plugin module, and https://maven.apache.org/guides/mini/guide-multiple-modules.html), which is not surprising because every plugin in Maven runs in a separate class loader. If it's not possible in Gradle, that would be one of the few cases where Gradle doesn't have feature parity.
A hacky way to do this is to run the newly-compiled plugin via Gradle's test kit runner.
A cleaner way to do this is to write plugins as thin shells of code written to Gradle's API that delegate the real work to plain old Java (or Kotlin) utility methods. This has a number of advantages:
You can unit test the utility methods.
You can use the utility methods for other purposes unrelated to the plugin.
You can call the utility methods directly from other modules in the project, thereby accomplishing what the plugin would have done if you could have built it and then called it in the same build.
To expand on the above answer.
Instead of calling the plugin like a plugin, add a main method that accepts the same parameters that Gradle plugin configuration passed to the plugin.
Then call the plugin's main using Gradle's Java exec task:
task(generateFoo, type: JavaExec) {
main = 'com.bar.Foo'
classpath = configurations.runtimeClasspath
args = ["arg1", "${projectDir}/src/generated/java"]
}
Note the args: those are the same pieces of information that used to be passed in via Gradle configuration:
apply plugin: 'foo-plugin'
generateFoo {
theArg "arg1"
outputDir "${projectDir}/src/generated/java"
}
Because the runtime classpath used by Java exec is the one for the calling module, you may encounter runtime classloader problems.
If that happens, it's easily fixed. Just change the rewritten plugin to a fat jar:
task fatJar(type: Jar) {
manifest {
attributes 'Implementation-Title': 'Foo Fat JAR', 'Main-Class': 'com.bar.Foo'
}
baseName = project.name + '-exec'
from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } }
with jar
}
artifacts {
archives fatJar
}
And then execute the fat jar with Java exec:
def fooGenerate = task(generateFoo, type: JavaExec) {
main = 'com.bar.Foo'
classpath = files("${projectDir}/../foo-plugin-module/build/libs/foo-plugin-module-exec.jar")
args = ["arg1", "${projectDir}/src/generated/java"]
}
Finally, make the dependent module's compile task depend on the code generation:
compileJava.mustRunAfter fooGenerate
If you use the fatJar approach, you don't even need to declare implementation project(":foo") in the dependent modules.
It might be also be possible to use Gradle's composite builds for this (https://docs.gradle.org/current/userguide/composite_builds.html).

Test classes in Groovy don't see test classes in Kotlin

I have gradle project with Kotlin plugin.
In my project I uses groovy and Spock for tests.
One of utility classes used in tests in written in Kotlin and I put it to src/test/kotlin
I'm trying to use this class from groovy tests (Spock specification), I see that "compileTestKotlin" task runs first and compiles my utility class, but still "compileTestGroovy" fails, because it does not see it.
How can I fix this situation?
How to add build/classes/kotlin/test/ to the compilation classpath of groovy tests?
The issue is that by default compileTestGroovy doesn't include build/classes/kotlin/test folder, so your Kotlin util class cannot be seen from Groovy tests.
In order to fix it you can manually add Kotlin test sources to compileTestGroovy's classpath. Add the following to your build.gradle:
compileTestGroovy.classpath += files(compileTestKotlin.destinationDir)
// in more recent versions it must be
compileTestGroovy.classpath += files(compileTestKotlin.destinationDirectory)
If your build file is build.gradle.kts, add the following
// make groovy test code depend on kotlin test code
tasks.named<GroovyCompile>("compileTestGroovy") {
classpath += files(tasks.compileTestKotlin)
}

Getting jacoco code coverage at the same as running tests

I have jacoco set up for my project.
I can do:
gradle cleanTest test
followed by
gradle jacocoTestReport
and get code coverage
This means two steps. Is there any way, I can just pass a switch to gradle test and get it
https://docs.gradle.org/current/userguide/jacoco_plugin.html
If the Java plugin is also applied to your project, a new task named
jacocoTestReport is created that depends on the test task.
So just call gradle jacocoTestReport, the test will also be invoked first.
edit : if you really want to call the test task, just add this in your build.gradle :
test.finalizedBy jacocoTestReport

gradle bootRun > Use test classpath

The problem I was having, was that I wanted to include test classpath resources in SpringBoot's bootRun gradle task. Why? So that I could use a test profile with test resources, to mock integration points.
What I tried:
The spring boot documentation only offers the addResources = true option (I tried using customConfiguration as per the similar bootRepackage configuration, to no avail)
No additional options are visible by looking at the BootRunTask source code
The equivalent maven plugin has a plethora of options, including useTestClasspath (which isn't mirrored in the gradle version)
I came across the following solution, which solved this issue for me.
Basically, the BootRunTask extends the standard JavaExec task, which offers a classpath option. So, you can add the test classpath resources by using the following gradle configuration:
bootRun {
classpath = sourceSets.test.runtimeClasspath
}

Resources