How to exlude tests from included dependecies - gradle

We have a gradle file where the upper webservices is dependent of the lower project core.
In the build.gradle of webservices the dependecy is included:
dependencies {
implementation project(':core')
}
But now things are going strange. When I run a test inside IntelliJ the whole test of core will start until finally the single test case of webservices will start.
Even on the command line I run into the same problem:
/opt/gradle/gradle-7.5.1/bin/gradle webservices:test --tests com.example.MyTests.test
end in the funny behaviour that the complete core test are running:
> Configure project :core
> Task :core:test
In the test section of webservices is nothing else as:
test {
useJUnitPlatform()
}
Trying to exclude the tests of core by adding something like
exclude '**/core/**'
are not ending in the behaviour I would expect.
It there a way to tell gradle not include the tests of the project which is inside the depedency?
EDIT: Add some information after User51 comment:
/opt/gradle/gradle-7.5.1/bin/gradle web:test --dry-run
> Configure project :core
BUILD NUMBER: -1
BUILD DATE: 2023-02-02_08-58-47
clean synchronize dir
spi.Extension touched!...
:abc:compileJava SKIPPED
[...]
:abc:test SKIPPED
:abc:jar SKIPPED
:core:compileJava SKIPPED
[...]
:core:test SKIPPED
:core:updateTestTimestamps SKIPPED
:core:jar SKIPPED
:webservices:wsdl2javaTask SKIPPED
:webservices:compileJava SKIPPED
[...]
:webservices:test SKIPPED
Futher in the build.gradle of core is written this:
if (project.hasProperty("RUN_TESTS_FOR_JAR") && RUN_TESTS_FOR_JAR.equals("false")) {
println "Tests are skipped!..."
jar.dependsOn(updateTestTimestamps)
} else {
jar.dependsOn(test, updateTestTimestamps)
}
build.dependsOn(updateTestTimestamps)
Thanks,
Markus

Related

How to run a single test that is excluded

I have integration tests named with "IT" at the end and the tests are excluded by default. My build.gradle contains:
test {
if (!project.hasProperty('runITs')) {
exclude '**/**IT.class'
}
}
The check task, which is part of build, no longer runs integration tests. All tests (unit + integration) are executed with defined runITs (e.g. ./gradlew -PrunITs=1 check) if it is necessary.
It works very well. The only drawback is than I can't run single integration test with --test (used by IDE) without runITs defined. The command fails with message: No tests found for given includes: [**/**IT.class](exclude rules).
Is there any way (e.g. build variable) how to recognize the run of single test with --test and skip the exclusion?
I have found a solution. My build.gradle now contains:
test {
if (!project.hasProperty('runITs') && filter.commandLineIncludePatterns.empty) {
exclude '**/**IT.class'
}
}
When tests are run with --tests then the list commandLineIncludePatterns in filter is not empty and exclude is not applied.
Details are obvious in test task source: https://github.com/gradle/gradle/blob/dc8545eb1caf7ea99b48604dcd7b4693e79b6254/subprojects/testing-base/src/main/java/org/gradle/api/tasks/testing/AbstractTestTask.java
try invoking the test task to the specific sub-project. if the test is root try
gradle -PrunITs=1 :test --tests 'MServiceTest'
else
gradle -PrunITs=1 :sub-prj:test --tests 'MServiceTest'

Gradle: Make a project depend on the output of another project in a multi project build

I have two projects in a multi project build. One looks like this:
// project-a build.gradle
task generateJar(type: Exec) {
commandLine "command", "to", "generate", "jar"
}
task generateArtifact(type: Zip, dependsOn: generateJar) {
outputs.file("/path/to/generated/jar")
}
artifacts { archives generateArtifact }
And the other simply depends on it like so:
// project-b build.gradle
dependencies {
implementation project(':project-a')
}
My expectation is that when I run a build on project b, it will first try to run generateArtifact + generateJar from project a, then get the outputted jar for use in project b, however I just get a "package does not exist" error in :project-b:compileJava. Based on the output, it looks like it is not trying to run any tasks in project-a, almost like it doesn't recognize the dependency exists
It looks like you're mixing up project and task dependencies. While you correctly made project-b depend on project-a, that does not automatically mean your custom generateJar and generateArtifact tasks get executed. You still need to mark your JAR in project-a as an "outgoing" artifact or add it to the output of the main source set which you can depend on in the consuming project like so:
sourceSets {
main {
output.file(generateArtifact.outputFile, builtBy: generateArtifact)
}
}
With 'compile' split into 'implementation' and 'api' configuration the behaviour might have changed. Can you just try with 'compile'(its deprecated though) once, to validate this. If it works then it means as suggsted by #sschuberth you may have to handle to explicitly call the generateArtifact of :projecta when you build :projectb.

Gradle subprojects: how do I execute `check` only on main project?

I added a subproject to my gradle project and now whenever I execute the target check, it also runs the tests on my subproject.
I was hoping that I could run the check-task on the main project by specifying it as absolute task as
gradle :check
or
gradle ::check
but both commandlines still execute all tests.
Any idea?
There is no way around this, so you would need to restructure your build (I think check task of the parent is by definition a aggregate of the sub-projects). You can have sub-projects depending on each other, I assume that might be what you want to model in your build.
Let's assume you have the sub-projects core and myModule.
If you want myModule to depend on (and use the output of) core, you add a project dependency to myModule:
dependencies {
compile project(':core')
}
This will also setup the task dependencies correctly.
you can access the task-graph of a subproject from the main projects `build.gradle' and disable tasks.
This way you can disable the task when you call it on the main project, but it will still be enabled when you call the build file of the subproject directly:
project('subproject') {
//disable 'check' and 'test' task
gradle.taskGraph.whenReady {
tasks.find {it.name=="check"}.enabled=false
tasks.find {it.name=="test"}.enabled=false
}
}

Gradle - get dependency list for each library/module

I am trying to get the dependencies list for each modules/library in a project.
Here is the structure of the project:
Project
+ --- library1
+ --- library2
+ --- library3
+ --- library4
+ --- library3
The build.gradle of project is
dependencies {
compile project(':library1')
}
library2 and library4 all depend on library3. and the way they compile dependencies are the same with project.
I would want to get the dependencies for each modules/libraries so that i can decide the sequence of bumping version for these libraries and uploading to maven in a script file.
So I would first want to save these dependencies for each module in a variable and the script file can read it and do the automation work.
I have tried using Conifguration.getAllDependencies() in custom gradle build file. But it doesnt work.
Anyone know how would I do that?
Any suggestions would be much appreciated!
====
UPDATE:
I have tried adding a task under project's gradle file
List<ProjectDependency> dependencies =
project.configurations.collectMany {
it.allDependencies
}.findAll {
it instanceof ProjectDependency
}
But the dependencies returns 0 size of list
For a simple project, one can get its dependencies by invoking
project.configurations*.
dependencies*.
findAll { it instanceof ExternalDependency }.
flatten()
Note that ExternalDependency, not ProjectDependency is used.
For dealing with dependencies on a real project, gradle-versions-plugin by Ben Manes offers some nice reports
gradle-dependency-lock plugin by Netflix provides dependency update automation

Creating a post build copy task with Gradle

I am struggling with the Gradle build lifecycle; specifically with the split between the configuration and execution phases. I have read a number of sections in the Gradle manual and have seen a number of ideas online, but have not found a solution to the following problem:
I want to run a specific task to produce an artifact at the end of my java-library-distribution build that is a flattened version of the runtime configuration jars. That is, I only want to produce the artifact when I run the specific task to create the artifact.
I have created the following task:
task packageSamplerTask(type: Tar, dependsOn: distTar) {
description "Packages the build jars including dependencies as a flattened tar file. Artifact: ${distsDir}/${archivesBaseName}-${version}.tar"
from tarTree("${distsDir}/${archivesBaseName}-${version}.tar").files
classifier = 'dist'
into "${distsDir}/${archivesBaseName}-dist-${version}.tar"
}
Although this task does produce the required artifact, the task runs during gradle's configuration phase. This behavior has the following consequences:
Irrespective of which task I run from the command line, this packageSamplerTask task is always run, often unnecessarily; and
If I clean the project, then the build fails on the next run because $distsDir doesn't exist during the configuration phase (obviously).
It appears that if I extend the Copy task in this manner I'm always going to get this kind of premature behavior.
Is there a way to use the << closure / doLast declarations to get what I want? Or is there something else I'm missing / should be doing?
Update
After further work I have clarified my requirements, and resolved my question as follows (specifically):
"I want to package my code and my code's dependencies as a flat archive of jars that can be deployed as a jMeter plugin. The package can then be installed by unpacking into the jMeter lib/ext directory, as is. The package, therefore, must not include the jMeter jars (and their dependencies) which are used for building and testing"
Because Gradle doesn't appear to support the Maven-like provided dependency management, I created a new configuration for my package which excludes the jMeter jars.
configurations {
jmpackage {
extendsFrom runtime
exclude group: 'org.apache.jmeter', name: 'ApacheJMeter_core', version: '2.11'
exclude group: 'org.apache.jmeter', name: 'ApacheJMeter_java', version: '2.11'
}
}
And then created the following task (using the closure recommendation from Peter Niederwieser):
task packageSamplerTask(type: Tar, dependsOn: assemble) {
from { libsDir }
from { configurations.jmpackage.getAsFileTree() }
classifier = 'dist'
}
This solution appears to work, and it allows me to use just theGradle java plugin, too.
The task declaration is fine, but the flattening needs to be deferred too:
...
from { tarTree("${distsDir}/${archivesBaseName}-${version}.tar").files }
Also, the Tar file should be referred to in a more abstract way. For example:
from { tarTree(distTar.archivePath).files }
First your task isn't executed in the configuration phase but like EVERY task it is configured in that phase. And your closure is just a configuration of your task (a Configuration closure, not an Action closure). That is why your code is "executed" in the configuration phase".
If you want your code to be executed in the execution phase have to write it in a doLastclosure or doFirst. But in your case it is better to keep it in a configuration closure, because you are configuring your task.
To make sure your build doesn't fail because of the missing folder, you can create it with distsDir.mkdirs().

Resources