Integrating with Gradle
The Teamscale Gradle Plugin enables seamless integration between your Gradle builds and Teamscale, allowing you to upload test reports, coverage data, and leverage Test Impact Analysis (TIA) capabilities. The plugin also provides utilities for aggregating and compacting reports to reduce their storage footprint.
It is split into two cooperating pieces.
- The
com.teamscaleplugin, applied to each project, instruments individual test tasks: it attaches a coverage agent to the JVM, collects execution data per test, and optionally enables Test Impact Analysis so only tests affected by recent changes are run. It also exposesTeamscaleUploadtasks that send those reports to the Teamscale server. - The
com.teamscale.aggregationplugin, applied once at a project that depends on all projects from which data should be aggregated (e.g. the root project or the application project), acts as a collection point: it pulls the coverage and JUnit XML produced by all projects it depends on (also transitively), merges them into a single report per test suite before they are uploaded.
Option Reference
For the full task and property reference, see our Gradle plugin reference.
Common Scenarios
Single project
If you only have a single Gradle project with no subprojects, follow the Setup section only.
Application project with many library sibling projects
If you have a root project with many subprojects, one of which is the main application and the others are libraries the application depends on, follow the Setup section, then also follow Aggregation for Multi-Project Builds and apply com.teamscale.aggregation to the application project.
Root project with many subprojects
If you have a root project with many subprojects, follow the Setup section, then also follow Aggregation for Multi-Project Builds and apply com.teamscale.aggregation to the root project.
Separate aggregation project
If you already have a separate subproject that does not contain code but solely handles e.g. report publishing, follow the Setup section, then also follow Aggregation for Multi-Project Builds and apply com.teamscale.aggregation to that project. Make sure that this project has a dependency on all projects from which data should be aggregated.
Setup
Apply the Plugin
Add the Teamscale plugin to your build scripts (latest version). You must add it to each project that runs tests for which you want coverage or test results in Teamscale.
plugins {
id "com.teamscale" version "35.0.2"
}Configure the teamscale Extension
The teamscale extension configures the connection to Teamscale. Configure once in the project that should perform the report upload to Teamscale, e.g. the root project.
teamscale {
server {
url = 'https://mycompany.teamscale.io/'
project = 'my-project'
userName = 'build'
userAccessToken = property('teamscale.access-token')
}
}By default, the plugin tries to detect the commit from CI environment variables (supported environment variables) or the local Git repository. If you need to manually specify a commit or baseline, see the full options reference. If auto-detection fails (e.g., building outside a Git repository without CI environment variables set), the upload will fail. In that case, set commit.revision explicitly.
Upload Reports
Register a TeamscaleUpload task to send test results and coverage to Teamscale.
import com.teamscale.TeamscaleUpload
tasks.register('teamscaleTestUpload', TeamscaleUpload) {
partition = "Unit Tests"
from(tasks.test)
from(tasks.jacocoTestReport)
}Run the Upload Task
Run the upload task to execute your tests and send the results to Teamscale:
./gradlew teamscaleTestUpload --continueWe recommend using --continue if you have multiple projects and want test results/coverage even if the tests of one project fail.
The upload task depends on the test and coverage tasks, so they run automatically. After the build completes, the data is available in Teamscale:
- Test results: visible in the Metrics > Tests perspective of your project
- Coverage: visible in the Test Gaps and Metrics > Code perspective
Aggregation for Multi-Project Builds
For projects with multiple subprojects, we recommend to aggregate reports before uploading them. This reduces the amount of data that needs to be processed by Teamscale. The plugin works similarly to Gradle's JaCoCo Report Aggregation Plugin and Test Report Aggregation Plugin. Please refer to the Gradle documentation for more details on the concepts behind the aggregation mechanism.
Apply the Plugins
Apply both plugins to the aggregation project:
plugins {
id "com.teamscale"
id 'com.teamscale.aggregation'
}Register Subprojects for Aggregation
The plugin adds the reportAggregation Gradle dependency configuration. You register subprojects in it the same way you declare library dependencies - Gradle then resolves test outputs from those projects for aggregation. There are two typical scenarios:
- The aggregation project is a JVM project itself - i.e., the aggregation happens in the project that also applies the
applicationplugin. In this case thereportAggregationconfiguration will automatically depend on all transitive projects and hence aggregate their reports. - The aggregation project is a standalone project - i.e., the project contains no code and has no dependencies to other projects declared. This is usually the case if aggregation happens via the root project or a dedicated subproject that just exists for the purpose to aggregate data. In this case you have to ensure that the projects that you want to aggregate are added as dependencies to the
reportAggregationconfiguration.
plugins {
id 'com.teamscale.aggregation'
}
dependencies {
// either register each project from which data should be aggregated separately:
reportAggregation(project(":lib:lib1"))
reportAggregation(project(":lib:lib2"))
// alternatively, if you want to aggregate data from all subprojects:
reportAggregation(subprojects())
}Register Upload Tasks
With JVM Test Suites
When using the JVM Test Suite Plugin, aggregate reports and their tasks are automatically created for each test suite - you only need to register a TeamscaleUpload task that collects from them. See the Gradle Plugin Reference for the full list of auto-created task types.
plugins {
id 'com.teamscale.aggregation'
}
tasks.register('teamscaleIntegrationTestReportUpload', TeamscaleUpload) {
partition = 'Integration Tests'
from(tasks.named('integrationTestAggregateCompactCoverageReport'))
from(tasks.named('integrationTestAggregateJUnitReport'))
}Without JVM Test Suites
If your build differentiates different test types only by package/class name rather than using the JVM Test Suite Plugin, no aggregate tasks are created automatically. Use the following approach to explicitly register each test type for separate aggregation. You will need one Test task for each type of test that you want to differentiate in the Teamscale UI.
You can associate a Test task with an arbitrary test suite name. For this purpose we provide the TestSuiteCompatibilityUtil.exposeTestForAggregation(testTask, suiteName). Call this for each task in each subproject that you want to take part in aggregation.
import com.teamscale.aggregation.TestSuiteCompatibilityUtil
tasks.register('unitTest', Test) {
// ...
}
tasks.register('systemTest', Test) {
teamscale {
collectTestwiseCoverage = true
}
}
TestSuiteCompatibilityUtil.exposeTestForAggregation(tasks.named('unitTest'), 'myUnitTestSuite')
TestSuiteCompatibilityUtil.exposeTestForAggregation(tasks.named('systemTest'), 'mySystemTestSuite')In the aggregation project, create an aggregation report for each type of data you want to aggregate (coverage, test results, testwise coverage) and each test suite name you picked:
import com.teamscale.aggregation.compact.AggregateCompactCoverageReport
import com.teamscale.aggregation.junit.AggregateJUnitReport
import com.teamscale.aggregation.testwise.AggregateTestwiseCoverageReport
plugins {
id 'com.teamscale.aggregation'
}
reporting {
reports {
unitTestAggregateCompactCoverageReport(AggregateCompactCoverageReport) {
testSuiteName = 'myUnitTestSuite'
}
unitTestAggregateJUnitReport(AggregateJUnitReport) {
testSuiteName = 'myUnitTestSuite'
}
systemTestAggregateTestwiseCoverageReport(AggregateTestwiseCoverageReport) {
testSuiteName = 'mySystemTestSuite'
}
}
}
tasks.register("teamscaleUnitTestReportUpload", TeamscaleUpload) {
partition = "Unit Tests"
from(tasks.named('unitTestAggregateCompactCoverageReport'))
from(tasks.named('unitTestAggregateJUnitReport'))
}
tasks.register("teamscaleSystemTestReportUpload", TeamscaleUpload) {
partition = "System Tests"
from(tasks.named('systemTestAggregateTestwiseCoverageReport'))
}Troubleshooting
Log Files
When debugLogging is enabled in the teamscale extension on a Test task, the plugin creates detailed log files to help diagnose issues:
logs/teamscale-jacoco-agent.log- Debug logs from the Java profilerengine.log- Debug logs from the impacted test engine
tasks.register('unitTest', Test) {
teamscale {
collectTestwiseCoverage = true
runImpacted = true
debugLogging = true
}
}These log files will be located in the test task's JaCoCo destination directory (e.g., build/jacoco/unitTest/).
Spring Boot: Missing Dependencies
Spring boot uses its own dependency versioning mechanism, not the Gradle built-in one. This can lead to problems when adding the com.teamscale.aggregation plugin. You'll see error messages like this one:
Could not find org.springframework.boot:spring-boot-starter-validation:.
Required by:
root project 'myproject' > project :subprojectThe aggregateReportResults configuration is where the plugin resolves reports from subprojects. Setting transitive = false prevents Gradle from following Spring Boot's BOM transitive dependencies into the aggregation resolution, which causes the version conflict.
In the project with the aggregation plugin, add:
dependencies {
reportAggregation(subprojects)
}
configurations.aggregateReportResults {
transitive = false
}