Gradle test suite on precompiled inherit implementation dependencies - gradle

I have a testing suite defined on a precompiled script as follows:
...
testing {
suites {
val integrationTest by registering(JvmTestSuite::class) {
testType.set(TestSuiteType.INTEGRATION_TEST)
}
}
}
...
And I have a multi-module project and the test dependencies inherit the dependencies of the module. Example:
dependencies {
implementation(project(":book"))
}
The project book will be available for the test sources.
I want the same thing to happen to the integrationTest sources. How can I do that?
I don't have to manually have to do in the previous example this:
dependencies {
implementation(project(":book"))
integrationTestImplementation(project(":book"))
}
Thanks

Related

Gradle 7: how to get list of implementation dependencies (including sub) in a task?

I need to have full list of dependencies necessary to run a project (so subdependencies are also important!).
task generateLibsDescriptor() {
doFirst {
configurations.compileClasspath.resolvedConfiguration.resolvedArtifacts.each {
println it
}
}
}
This code works, but there are also compileOnly dependencies listed. I tried to change compileClasspath to implementation, but had an error Resolving dependency configuration 'implementation' is not allowed as it is defined as 'canBeResolved=false'.
Is it possible to have a list of just implementation dependencies (with subdependencies)?
Configuration compileClasspath extends compileOnly and implementation. New config should be created which extends only implementation but resolvable.
configurations {
resolvableImpl.extendsFrom(implementation)
resolvableImpl.canBeResolved(true)
}
task generateLibsDescriptor() {
doFirst {
configurations.resolvableImpl.resolvedConfiguration.resolvedArtifacts.each {
println it
}
}
}

Creating a fat jar using Kotlin and Gradle - compile vs implementation?

I'm tinkering with a simple "hello world" project in Kotlin & Gradle (see below). I've added the "fat jar" collection stuff to bring in the Kotlin dependency, but when I try to run java -jar build/libs/hello-1.0-SNAPSHOT.jar I get the java.lang.NoClassDefFoundError: kotlin/jvm/internal/Intrinsics error because the dependencies aren't available at runtime.
I've solved that problem by changing implementation to compile, which makes everything work fine. But from what I understand, we shouldn't be using compile anymore, and neither api nor implementation makes the "fat jar" collection process work, and as I look at the other options for dependencies I'm not sure which to use.
Question: what's the "right" thing to do in a case like this?
// build.gradle
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.3.41'
}
group 'com.example.test'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
// if I change "implementation" to "compile", running the jar works
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
}
jar {
manifest {
attributes "Main-Class": "ApplicationKt"
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
}
// Application.kt
fun main(args: Array<String>) {
println("hello world")
}
The compile dependency is deprecated. You should use implementation to declare your implementation dependencies, and compileClasspath to get all the compilation dependencies.

Avoiding Duplicate Repository Declaration in Multi Module Gradle Project

Lets say I have two projects in a multimodule gradle (4.2) repository with the following configurations:
Project A build.gradle:
dependencies {
compile (group: 'org.example', name: 'dependency-of-vast-importance', version: '17.2') {
}
repositories {
maven {
url "http://download.example.org
}
}
Project B build.gradle:
dependencies {
compile project(":projectA")
compile (group: 'org.anotherdependency', name: 'anotherdependency', version: '1.0')
}
repositories {
maven {
url "http://download.anotherdependency.org
}
}
With this configuration, Project B will fail to build -claiming in cannot find dependency-of-vast-importance.
So far, the only "solution" I have found for successfully completing the build requires writing the build.gradle for projectB like:
dependencies {
compile project(":projectA")
compile (group: 'org.anotherdependency', name: 'anotherdependency', version: '1.0')
}
repositories {
maven {
url "http://download.anotherdependency.org
}
maven {
url "http://download.example.org
}
}
This approach is worthless because it requires that I copy the repository declarations for ProjectA to all other projects that depend on it -which defeats the purpose of dependency management and modules.
How can I avoid specifying all the repositories necessary for Project A in Project B's build.gradle?
Use in root build.gradle:
allprojects {
repositories {
maven { url 'http://download.anotherdependency.org' }
maven { url 'http://download.example.org' }
}
}
This code will apply repositories to all projects

How to use JaCoCo Gradle Plugin with TestNG and JUnit?

I am working on a project where we are using TestNG and JUnit for our tests.
Unfortunately when writing TestNG tests they are not considered in JaCoCo Coverage Reports.
I wrote a testng.gradle file, which I include in each of the build.gradle files (it's a multi-module project):
task testNG(type: Test) { useTestNG() }
test.dependsOn testNG
Both JUnit and TestNG tests work this way.
If I write my testng.gradle like this:
test {
useTestNG()
}
JaCoCo works properly, but obviously only TestNG tests get executed.
How can I fix it? Is it a bug in Gradle's JaCoCo plugin?
Seems that while Gradle JaCoCo Plugin enhances testNG task, so that its execution uses JaCoCo Java agent, but it forgets to update jacocoTestReport task, so that this task doesn't use results of execution of testNG task. Don't know if this is a bug or on purpose, but solution is provided below.
to demonstrate this
file src/main/java/Example.java:
public class Example {
public void junit() {
System.out.println("JUnit");
}
public void testng() {
System.out.println("TestNG");
}
}
file src/test/java/ExampleJUnitTest.java:
import org.junit.Test;
public class ExampleJUnitTest {
#Test
public void test() {
new Example().junit();
}
}
file src/test/java/ExampleTestNGTest.java:
import org.testng.annotations.Test;
public class ExampleTestNGTest {
#Test
public void test() {
new Example().testng();
}
}
file build.gradle:
apply plugin: 'java'
apply plugin: 'jacoco'
repositories {
mavenCentral()
}
dependencies {
testCompile 'org.testng:testng:6.8.8'
testCompile 'junit:junit:4.12'
}
task testNG(type: Test) {
useTestNG()
}
test {
dependsOn testNG
}
After execution of gradle clean test jacocoTestReport -d you'll see in log
java ... -javaagent:.../jacocoagent.jar=destfile=build/jacoco/testNG.exec ...
...
java ... -javaagent:.../jacocoagent.jar=destfile=build/jacoco/test.exec ...
and that directory build/jacoco contains two files - testNG.exec and test.exec, for testNG and for test tasks respectively. While JaCoCo report shows only execution of JUnit by test task.
to solve this
Either instruct task testNG to write execution data into same file as test:
task testNG(type: Test) {
useTestNG()
jacoco {
destinationFile = file("$buildDir/jacoco/test.exec")
}
}
Either instruct task jacocoTestReport to also use testNG.exec file:
jacocoTestReport {
executionData testNG
}
I'm assuming that the same should be done for the case of multi-module project in general and in your case in particular, since Minimal, Complete, and Verifiable example of your multi-module project setup wasn't provided.
The second solution from #Godin's fixed it for me. But to add on that, I found that testNG is not recognized by gradle since it is not matching the right *.exec file under $buildDir/jacoco. In my case it is testNg.exec, so it worked after I include this block in my subproject's build.gradle:
jacocoTestReport {
executionData testNg
}
The first solution does not work for me
task testNG(type: Test) {
useTestNG()
jacoco {
destinationFile = file("$buildDir/jacoco/test.exec")
}
}
I guess it is because the testNG is overwriting the whole file $buildDir/jacoco/test.exec generated from JUnit.

Is there a Gradle task to download testRuntime dependencies?

Is there a command that will instruct Gradle to resolve and download all testRuntime dependencies, but not run the tests?
Preferably, I want to do this without writing a custom task (such that the command can be run against any Gradle project).
For example, if my build.gradle has this dependency:
dependencies {
// ...
testRuntime "org.seleniumhq.selenium:selenium-htmlunit-driver:2.47.1"
}
The JAR files associated with selenium-htmlunit-driver are not downloaded until I run gradle test, which also runs the tests. I can download all other dependencies by running gradle testClasses, but not the testRuntime deps.
Put the following in a file called resolve.gradle
gradle.allprojects { project ->
project.task('resolveTestRuntime') {
doLast {
project.configurations.testRuntime.resolve()
}
}
}
Then run resolve.gradle as an init script
gradlew --init-script resolve.gradle resolveTestRuntime
Modifying the answer from Lance Java into a valid Init script, I was able to accomplish this with the following resolve.gradle:
apply plugin:MyInitPlugin
class MyInitPlugin implements Plugin<Gradle> {
#Override
void apply(Gradle gradle) {
gradle.allprojects{ project ->
project.task('resolveTestRuntime') {
doLast {
project.configurations.testRuntime.resolve()
}
}
}
}
}
Then running:
gradlew --init-script resolve.gradle resolveTestRuntime

Resources