Gradle multi-project only executes tests for one project - gradle

I have a multi-project gradle build with four Kotlin Multiplatform modules, two of which have tests. When I run gradle check, if any of the tests from one of the modules fails, the tests for the other module do not get executed.
I'm using Gradle 7.3, Java 17 and kotlin.test. Tests for both projects are located in the commonTest source set. Also tried Gradle 7.1 and Java 11 with the same behavior.
Excerpt from settings.gradle.kts:
include(":ProjectA")
include(":ProjectB") // B has tests and depends on D, its tests are run
include(":ProjectC")
include(":ProjectD") // D has tests but are not run
Excerpt from ProjectB build.gradle.kts:
sourceSets {
val commonMain by getting {
dependencies {
api(compose.runtime)
api(compose.foundation)
api(compose.material)
implementation(project(":ProjectD"))
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test"))
}
}
From the output of gradle check I can see that :ProjectB:allTests gets executed and fails but :ProjectB:allTests never gets executed. This is an excerpt from the gradle output:
> Task :ProjectB:desktopTest
com.mylibrary.AppTest[desktop] > helloTestNg[desktop] FAILED
java.lang.AssertionError at AppTest.kt:8
2 tests completed, 1 failed
There were failing tests
> Task :ProjectB:allTests FAILED
FAILURE: Build failed with an exception.
If I do gradle -p ProjectD check tests for ProjectD are executed correctly.

Default Gradle behavior is to stop if any task fails, and Gradle considers a failing test as failing the check task. As a consequence, if any test fails in a certain project, the tests for the projects that have not yet been executed will not get executed.
The --continue can be useful in this case, it changes the default behavior and forces Gradle to continue executing all tasks even if some of them failed.
In this issue it is very well explained https://youtrack.jetbrains.com/issue/KT-49858p

Related

Gradle - how to prevent dependent submodule's tasks from running if dependent task fails?

In a multi-module project with modules mod-a and mod-b, mod-b has mod-a as a project lib dependency:
project(":mod_b") {
dependencies {
implementation project(':mod_a')
}
}
Both mod-a and mod-b are configured to publish Maven artifacts (jars) if their tests pass, using the maven-publish plugin:
// within each module's build.gradle
tasks.withType(AbstractPublishToMaven) {
dependsOn test
}
When I run Gradle with the --continue flag then if tests in mod-a fail then no mod-a artifacts are published. However, artifacts are published for mod-b. Why is this and how to I prevent this happening (I wish to continue to use the --continue option)?
e.g. this results in publishing of com.example:mod-b:x.y.z, when I do not wish it to:
./gradlew --continue clean publishToMavenLocal
i.e. if there were 3 modules (mod-a -depends-on-> mod-b -depends-on-> mod-c), then if only mod-b's tests fail and then only mod-a should be published).
The solution is to make the publish tasks also depend on the buildNeeded task. The buildNeeded task builds and tests all other projects that the project in question requires. Thus if a dependent task fails, buildNeeded will be marked as having failed and thus the publish task won't fire.

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 composite build execute tasks transitively

When executing gradle build in a composite gradle build only compileJava task is executed transitively. Others, like the test task are not.
How can I enforce that my tests are also run on build?
I tried:
build.dependsOn gradle.includedBuilds*.task(':build')
but that did not work.
https://docs.gradle.org/current/userguide/composite_builds.html
here is the gist:
// settings
if (file('../myModule').exists()) {
includeBuild('../myModule')
}
// build1
dependencies {
compile 'mygroup:MyModule:1.0.0'
}

Skipping tests when building with composite build in Gradle

I have 5 projects that are dependent. So I have made new 'dummy' project that is a composite build of these 5 projects and have the following task:
task build {
dependsOn gradle.includedBuilds*.task(':build')
}
I can run the build of all projects in composite using: gradlew build? Or how to this in other way?
How can I now pass the -x test to skip the test execution for composite build?
Instead of trying to exclude tasks (build tasks depend on test), you can use the assemble task instead:
task buildWithoutTests {
dependsOn gradle.includedBuilds*.task(':assemble')
}
According to the task listing (gradle tasks), the difference is:
assemble - Assembles the outputs of this project.
build - Assembles and tests this project.

Gradle sonarRunner plugin adds dependency for test, causing compilation and testing to run twice

I have a gradle project in scala to which I am trying to add sonarRunner. Things are working fine, but compilation and test is running twice on executing task sonarRunner as SonarRunner adds test as a dependency. However, scoverage always recompiles the code for instrumentation and then runs the tests.
Is there a way to avoid running the tests twice. I tried ignoring tests in sonarRunner task, but then test task won't run at all. I tried guarding ignore test in sonarRunner task by something like below mentioned code and that basically does not do anything.
task sonarRunner {
test {
gradle.taskGraph.whenReady { graph ->
if (graph.hasTask('sonarRunner')) {
enabled = false
}
}
}
dependsOn 'reportScoverage'
}
Any suggestion will be helpful.
You can remove the dependency to the test task by overriding the sonarRunner task's dependencies.
tasks.sonarRunner {
dependsOn = []
}

Resources