Testing Bundles / Plugins with Tycho
There are different ways to test bundles / plug-ins with Tycho:
maven-surefire-plugin
Using maven-surefire-plugin is the preferred way whenever you want to write a plain unit-test. This is a unit test that either:
- doesn't need an OSGi runtime
- uses some kind of mocking technique for OSGi (e.g. Apache Sling OSGi Mocks)
- or starts an embedded OSGi Framework (e.g. osgi-test-framework).
This requires:
- setting up your project using a test-source folder (see below), alternatively using the standard maven layout
- a configured execution of the
maven-surefire-plugin:testgoal - packaging
eclipse-pluginis used
A sample snippet looks like this:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
...
<build>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${surefire-plugin-version}</version>
<executions>
<execution>
<id>execute-tests</id>
<goals>
<goal>test</goal>
</goals>
</execution>
</executions>
</plugin>
</build>
</project>
To execute the tests, one has to invoke maven with mvn test.
The following demo projects are provided as an example:
- Project with a configured source folder: https://github.com/eclipse-tycho/tycho/tree/master/demo/testing/surefire/with-source-folder
- Project using maven standard layout: https://github.com/eclipse-tycho/tycho/tree/master/demo/testing/surefire/with-maven-layout
tycho-surefire-plugin
The tycho-surefire-plugin is the preferred whenever you want to write tests that require an OSGi Framework running and is executed in the integration-test phase of your build, this is similar to what PDE offers as Plugin Tests.
There are two ways to use this:
- You use the
eclipse-test-pluginpackaging, and with those your plugin must only contain test-classes and they will be executed automatically as part of the integration-test phase of your build. This approach is not recommended for new designs. - You use
eclipse-pluginpackaging and configure an additional execution of thetycho-surefire-plugin:plugin-testgoal with either a test-source folder (see below), alternatively using the standard maven layout.
A sample snippet looks like this:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
...
<build>
...
<plugin>
<groupId>org.eclipse.tycho</groupId>
<artifactId>tycho-surefire-plugin</artifactId>
<version>${tycho-version}</version>
<executions>
<execution>
<id>execute-integration-tests</id>
<goals>
<goal>plugin-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
</build>
</project>
To execute the tests, one must invoke maven with mvn verify, the following demo projects are provided as an example:
- Project with a configured source folder as a standalone project similar to the discouraged
eclipse-test-pluginpackaging: https://github.com/eclipse-tycho/tycho/tree/master/demo/testing/tycho/standalone - Project using maven standard layout having the tests in the same module: https://github.com/eclipse-tycho/tycho/tree/master/demo/testing/tycho/samemodule
bnd-testing
The tycho-surefire-plugin has also support for bnd-testing,
this is like plugin-test but uses the BND testing framework. There is currently no JDT/PDE equivalent but this integrates nicely with the OSGi Testing Support and allows to execute pre-built test-bundles.
A sample snippet looks like this:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
...
<build>
...
<plugin>
<groupId>org.eclipse.tycho</groupId>
<artifactId>tycho-surefire-plugin</artifactId>
<version>${tycho-version}</version>
<executions>
<execution>
<id>execute-integration-tests</id>
<goals>
<goal>bnd-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
</build>
</project>
To execute the tests, one has to invoke maven with mvn verify, the following demo projects are provided as an example:
-
Project with maven standard layout having the tests in the same module and using OSGi JUnit5 annotations to automatically inject services:
-
https://github.com/eclipse-tycho/tycho/tree/master/demo/testing/bnd/osgi-test
tycho-test-plugin
The tycho-test-plugin is a new plugin introduced in Tycho 6 to provide unified testing of OSGi bundles. Unlike previous approaches, it is no longer bound to surefire and offers better integration with modern testing frameworks.
junit-platform mojo
The tycho-test:junit-platform mojo integrates the JUnit Platform Console Launcher into any OSGi Framework.
This approach has several advantages:
- Tycho is completely independent from the used JUnit framework version (since it calls it via a command-line interface)
- Better and more natural integration of selecting test engines in the pom.xml or with the target platform
- You can use any of the JUnit provided test engines or new features that might be added
This requires:
- packaging
eclipse-pluginis used - a configured execution of the
tycho-test:junit-platformgoal - JUnit Platform dependencies (console launcher and test engines) as test-scoped dependencies
A sample snippet looks like this:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
...
<build>
...
<plugin>
<groupId>org.eclipse.tycho</groupId>
<artifactId>tycho-test-plugin</artifactId>
<version>${tycho-version}</version>
<executions>
<execution>
<id>execute-tests</id>
<goals>
<goal>junit-platform</goal>
</goals>
</execution>
</executions>
</plugin>
</build>
<dependencies>
<!-- The API is used at compile time of the bundle -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit-version}</version>
<scope>compile</scope>
</dependency>
<!-- The console and the engine are only required at test execution time -->
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-console</artifactId>
<version>${junit-version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit-version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
To execute the tests, one has to invoke maven with mvn verify. The following demo project is provided as an example:
combining different approaches
setup test source folders in eclipse
When working with Eclipse and PDE (Plugin Development Environment), you can mark source folders as containing test sources. This is important for Tycho to correctly identify and compile test classes separately from production code.
Marking a Source Folder as Test Source
To configure a source folder to contain test sources in Eclipse:
- Right-click on your Eclipse plugin project in the Package Explorer or Project Explorer
- Select “Properties” from the context menu
- Navigate to “Java Build Path” in the left panel
- Select the “Source” tab
- Locate the source folder you want to mark as a test source folder (e.g.,
src_test) - Expand the source folder entry by clicking on the arrow/triangle next to it to reveal its attributes
- Look for “Contains test sources: No” in the expanded view
- Double-click on “Contains test sources: No” or select it and click “Edit”
- In the dialog that appears, change the value to “Yes”
- Click “OK” to close the edit dialog
- Click “Apply and Close” to save the changes
Tip: After marking a source folder as a test source, you'll see “Contains test sources: Yes” in the build path configuration.
What This Does
When you mark a source folder as containing test sources, Eclipse modifies the .classpath file in your project to include a test attribute. For example:
<classpathentry kind="src" output="bin_test" path="src_test">
<attributes>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
How Tycho Uses This Information
Tycho reads the .classpath file to determine which source folders contain test code:
- Source folders without the test attribute (or with
test="false") are treated as production code and compiled during thecompilephase - Source folders with
test="true"are treated as test code and compiled during thetest-compilephase with test dependencies available
This allows you to:
- Keep test and production code in the same project
- Use different output directories for test and production classes
- Have test-specific dependencies that don't leak into your production bundle
Recommended Directory Structure
For projects that include both production and test code, a common structure is:
your-plugin-project/
├── src/ (production code)
├── src_test/ (test code, marked with test="true")
├── META-INF/
│ └── MANIFEST.MF
├── build.properties
└── pom.xml
Important Notes
- The test attribute is supported in Eclipse since version 4.8 (2018-09)
- When using pomless builds, Tycho automatically detects test source folders marked in the
.classpathfile - Test source folders should be included in the
build.propertiesfile if you want them to be part of the build - Make sure your
pom.xmlincludes the necessary test plugin configurations (eithermaven-surefire-pluginortycho-surefire-pluginwith appropriate executions)
Alternative: Manual .classpath Editing
If you prefer, you can also directly edit the .classpath file in your project root. Add or modify the classpathentry element for your test source folder to include the test attribute:
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<!-- Production source folder -->
<classpathentry kind="src" output="bin" path="src"/>
<!-- Test source folder with test attribute -->
<classpathentry kind="src" output="bin_test" path="src_test">
<attributes>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<!-- Other classpath entries -->
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="output" path="bin"/>
</classpath>
After editing, refresh your project in Eclipse (F5) for the changes to take effect.
Example Projects
See these demo projects for working examples:
- Surefire with source folder - Shows
src_testmarked as test source - Tycho standalone test - Shows a project with only test sources
- Tycho OSGi test - Shows mixed production and test sources
