Teamscale Maven Plugin
The Teamscale Maven Plugin provides integration between Maven-based builds and Teamscale.
Overview
The plugin offers the following main features:
- Test Impact Analysis (TIA) – Automatically fetches and executes only impacted tests
- Testwise Coverage Recording – Records coverage data per test case
- Coverage Upload – Uploads Testwise Coverage or JaCoCo coverage reports to Teamscale
Goals
The plugin provides the following goals:
| Goal | Description | Default Lifecycle Attachment |
|---|---|---|
prepare-tia-unit-test | Instruments Surefire unit tests to run impacted tests and collect Testwise Coverage | INITIALIZE |
prepare-tia-integration-test | Instruments Failsafe integration tests to run impacted tests and collect Testwise Coverage | PACKAGE |
testwise-coverage-report | Converts binary data produced during the tests to testwise coverage reports | VERIFY |
upload-coverage | Uploads JaCoCo and Testwise Coverage reports to Teamscale | VERIFY |
help | Displays help information for the plugin | - |
Usage
Add the plugin to your Maven POM file:
<project>
<properties>
<teamscale.plugin.version>35.0.2</teamscale.plugin.version>
</properties>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>com.teamscale</groupId>
<artifactId>teamscale-maven-plugin</artifactId>
<version>${teamscale.plugin.version}</version>
<configuration>
<teamscaleUrl>https://company.teamscale.io</teamscaleUrl>
<projectId>myProject</projectId>
<username>build</username>
<accessToken>myAccessToken</accessToken>
<includes>
<include>*com.company.*</include>
</includes>
<!-- More options see below -->
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>Check here for the latest version.
Test Impact Analysis
To perform Test Impact Analysis and/or collect Testwise Coverage you need to:
- Put the
impacted-test-engineon the test classpath. This JUnit engine is responsible for querying Teamscale for impacted tests, makes sure to only run the returned subset of tests and informs the coverage profiler about when tests start and end. - Run the
prepare-tia-unit-testand/orprepare-tia-integration-testgoals to attach the coverage profiler to the test JVM.
Apply those settings to all modules that contain relevant tests:
<project>
<dependencies>
<dependency>
<groupId>com.teamscale</groupId>
<artifactId>impacted-test-engine</artifactId>
<version>${teamscale.plugin.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>com.teamscale</groupId>
<artifactId>teamscale-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>prepare-tia-unit-test</goal>
<goal>prepare-tia-integration-test</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>You might also want to only add this conditionally. By moving the configuration into a profile you can enable TIA by running the build with -Dtia
<project>
<profiles>
<profile>
<id>tia</id>
<activation>
<property>
<name>tia</name>
</property>
</activation>
<!-- Configuration from above -->
</profile>
</profiles>
</project>The profiler produces binary data that needs to be converted into a proper report before it can be uploaded to Teamscale. The testwise-coverage-report goal is responsible for performing this conversion. The goal should only be run once, i.e., in your aggregator module (see below).
Limitations
- JUnit 5: The plugin only supports tests based on the JUnit Platform and frameworks built on it (e.g., Serenity).
- Surefire Version: TIA only supports Surefire versions >= 3.1.0
- Parallel Tests: TIA does not support parallelized tests. Ensure Surefire and Failsafe use:
<forkCount>1</forkCount>
<threadCount>1</threadCount>- Custom Test Execution: If your system-under-test is launched by means other than Surefire or Failsafe, ensure the
argLineproperty is passed to that JVM. You can also use another property by specifying it via thepropertyNameconfiguration.
Upload to Teamscale
The upload to Teamscale should typically only happen once for the whole build. To achieve this with Maven, you need an aggregator module that has a dependency (directly or indirectly) on all modules of your project. If you intend to collect Testwise Coverage, apply the plugin with the testwise-coverage-report goal in your aggregator module. If you intend to upload JaCoCo coverage, make sure to configure the JaCoCo Maven Plugin in the modules to generate XML reports.
<project>
<build>
<plugins>
<plugin>
<groupId>com.teamscale</groupId>
<artifactId>teamscale-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<!-- Only needed if you collect Testwise Coverage -->
<goal>testwise-coverage-report</goal>
<goal>upload-coverage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>Common Configuration Parameters
Some parameters can also be set via system properties on the command line (e.g., -Dteamscale.username=build). Parameters without a system property can only be configured via XML.
Authentication and Connection
| Parameter | System Property | Description | Required |
|---|---|---|---|
teamscaleUrl | - | URL of your Teamscale instance | Yes |
projectId | - | ID of your Teamscale project | Yes |
username | teamscale.username | Username for Teamscale authentication | Yes |
accessToken | teamscale.accessToken | Access token for Teamscale authentication | Yes |
Commit and Revision Specification
Teamscale needs to know which code commit the coverage belongs to. By default, the plugin tries to detect the commit from CI environment variables (supported environment variables) or the local Git repository. If needed, you can manually specify a commit using the parameters below.
| Parameter | System Property | Description | Default |
|---|---|---|---|
revision | teamscale.revision | Git commit hash (SHA1) to upload coverage to | Auto-detected from CI or Git |
repository | teamscale.repository | Connector ID in Teamscale to look up the revision. If not set, Teamscale searches all connectors configured in the project. | Not set (searches all) |
commit | teamscale.commit | Alternative: branch and timestamp in format BRANCH:UNIX_EPOCH_TIMESTAMP_IN_MILLISECONDS (e.g., main:1675123456789) | Not used when revision is set |
Precedence rules
- If
revisionis set, it takes precedence overcommit - If only
commitis set, it is used - If neither is set, the plugin auto-detects from CI environment variables or Git HEAD
If both are set, a warning is logged and revision is used.
When to use commit vs. revision
- revision (preferred): Use when you have a Git commit hash (standard for CI/CD pipelines)
- commit: Use when you need to specify a point in time on a branch (timestamp in Unix epoch milliseconds)
Code Coverage Control
The following patterns use wildcard syntax (not Ant patterns):
*matches any number of any characters (including slash, dot, etc.)?matches exactly one character
Patterns are matched against fully qualified class names (e.g., com.example.MyClass).
| Parameter | System Property | Description | Default |
|---|---|---|---|
includes | - | Patterns for classes to include in coverage instrumentation | * |
excludes | - | Patterns for classes to exclude from coverage instrumentation | Some packages that are often included during testing, e.g., junit, assertj, mockito,... |
Example:
<includes>
<include>*com.company.*</include>
</includes>
<excludes>
<exclude>*com.company.generated.*</exclude>
</excludes>TIP
Prefix patterns with * (e.g., *com.company.*) to handle nested JAR structures.
Two types of include/exclude patterns
The plugin has two separate sets of includes/excludes parameters:
Coverage Instrumentation (common configuration, used by
prepare-tia-*goals):- Applied at runtime during test execution
- Controls which classes are instrumented by the Java profiler
Report Generation (
testwise-coverage-reportgoal):- Applied during post-processing when generating the report
- Controls which compiled
.classfiles are analyzed - Defaults to
*(all classes)
In most cases, configure only the coverage instrumentation patterns in a common configuration.
Test Execution Control
| Parameter | System Property | Description | Default |
|---|---|---|---|
runImpacted | runImpacted | Whether to execute only impacted tests | true |
runAllTests | runAllTests | Whether to execute all tests regardless of impact | false |
skip | - | Whether to skip the execution of the goal | false |
Goal-Specific Parameters
TIA Configuration (prepare-tia-unit-test and prepare-tia-integration-test)
| Parameter | System Property | Description | Default |
|---|---|---|---|
unitTestPartition | teamscale.unitTestPartition | Partition name for unit test reports (prepare-tia-unit-test only) | "Unit Tests" |
integrationTestPartition | teamscale.integrationTestPartition | Partition name for integration test reports (prepare-tia-integration-test only) | "Integration Tests" |
propertyName | - | Property name for JVM arguments | argLine/spring-boot.run.jvmArguments/tycho.testArgLine |
additionalAgentOptions | - | Additional options for the Teamscale Java Profiler | None |
agentPort | - | Port for Java agent communication | Auto-selected |
debugLogging | debugLogging | Enable DEBUG level logging for the Java profiler and impacted test engine | false |
baselineCommit | - | Baseline for impact analysis | None |
baselineRevision | - | VCS revision for baseline | None |
Testwise Coverage Report (testwise-coverage-report)
This goal converts binary coverage data into a testwise coverage report. The includes and excludes parameters control which compiled class files are analyzed.
| Parameter | System Property | Description | Default |
|---|---|---|---|
includes | - | Wildcard patterns for class files to include during report generation | * |
excludes | - | Wildcard patterns for class files to exclude during report generation | None |
splitAfter | - | Number of tests after which to split coverage into multiple reports | 5000 |
Coverage Upload (upload-coverage)
| Parameter | System Property | Description | Default |
|---|---|---|---|
unitTestPartition | teamscale.unitTestPartition | Partition name for unit test reports | "Unit Tests" |
integrationTestPartition | teamscale.integrationTestPartition | Partition name for integration test reports | "Integration Tests" |
aggregatedTestPartition | teamscale.aggregatedTestPartition | Partition name for aggregated test reports | "Aggregated Tests" |
Troubleshooting
The plugin creates log files in the target/tia/ directory to help diagnose issues:
agent.log– Logs from the Java profilerengine.log– Logs from the impacted test engine
You can enable debug logging by adding the debugLogging configuration property or via the command line with -DdebugLogging=true:
<plugins>
<plugin>
<groupId>com.teamscale</groupId>
<artifactId>teamscale-maven-plugin</artifactId>
<version>${teamscale.plugin.version}</version>
<configuration>
<debugLogging>true</debugLogging>
<!-- More options -->
</configuration>
</plugin>
</plugins>If the log files are not created when executing your tests, check if you have <argLine>...</argLine> in your pom.xml and remove it. This overwrites the arguments we set in the plugin and thus de-registers the coverage profiler.
In some cases, the test reports generated by Surefire/Failsafe may also contain error information. You can find them under target/surefire-reports after all tests have finished. Check the stdout/stderr of failing tests for additional error messages.
If the build fails after applying the above POM changes but works without them, try to re-run the build with -e to discover the error that caused this.
If you notice largely increased test runtimes on systems that set <reuseForks>true</reuseForks> it is recommended to set the tiaMode to exec-file:
<plugins>
<plugin>
<groupId>com.teamscale</groupId>
<artifactId>teamscale-maven-plugin</artifactId>
<version>${teamscale.plugin.version}</version>
<configuration>
<tiaMode>exec-file</tiaMode>
<!-- More options -->
</configuration>
</plugin>
</plugins>Writing a testwise coverage report every time the JVM closes can be time-consuming, so writing raw .exec files instead, has been shown to increase test execution times. Have a look at the testwise-coverage-report goal for more information. You can use the upload-coverage goal to then upload the created testwise coverage report to Teamscale.
