Introduction

You cannot use direct integration of Tycho plugin with Clover using standard 'clover:setup' or 'clover:instrument' goals. The reason is Maven Tycho Plugin ignores Maven's source folders definitions. Instead of this, Tycho Plugin reads source folders locations from Eclipse configuration files (like build.properties). As a consequence it does not see files instrumented by Clover, which are stored in the target/src-instrumented directory.

Workaround

However, you can use a following trick, which is very similar to the one described in Instrumenting RCP Application / Approach#1 : Instrument source code manually:

 

1) Instrument all source files manually

The idea is to replace original sources with the instrumented version, still preserving the original project structure.

Use CloverInstr command line tool or clover-instr Ant task or clover:instrument to instrument sources manually - see script in Appendix 1.

(lightbulb) Remember to put instrumented sources in another location, i.e. not in your original workspace.  (smile)

Clover Database (clover.db) will be created during this process.

 

2) Build instrumented project

Build will use Maven Tycho Plugin to package everything. Because of fact that instrumented sources contain calls of Clover classes, you must have the Clover JAR available on classpath during compilation. The easiest way is to add org.openclover:clover dependency in the extraClasspathElements parameter of the tycho-compiler-plugin in a top-level module (see Appendix).

 

3) Run tests

Run any kind of tests - JUnit, manual ... - just to get coverage data. Coverage recordings will be stored in the same directory where Clover Database is located. 

Note that you must have the Clover runtime available during execution. The best is to add it to Java Xbootclasspath in order to ensure that Clover JAR is loaded before any OSGI bundle. If you are running:

  • unit tests via tycho-surefire-plugin then add <argLine>-Xbootclasspath/a:/path/to/clover-X.Y.Z.jar</argLine> in the Tycho Surefire Plugin configuration section (see Appendix)
  • manual tests in standalone product then add -Xbootclasspath/a:/your/path/to/clover.jar as JVM argument in Eclipse configuration file (eclipse.ini / config.ini)

 

4) Generate report

Run HtmlReporter command line tool or clover-report Ant task or the clover:clover Maven goal in order to generate report.

 

Appendix 1

Workbench configuration

The diagram below shows how work with manually instrumented sources (Approach #1) can be organized. A location of Clover database is configured in Ant script.

 

Code sample

You can clone examples provided by Tycho team: git clone http://git.eclipse.org/c/tycho/org.eclipse.tycho-demo.git

Go to "itp01" sample, rename it to "original_project", use Ant script from below and save it in directory above "original_project". Follow instructions below.

 

Ant script

Sample Ant script which instruments all *.java files from project.original.dir and puts them into project.instrumented.dir, preserving original directory structure. It copies all non-java files as well.

<project default="instrument">
    <property name="clover.jar" location="${user.home}/clover.jar"/>
    <property name="ant-contrib.jar" location="${user.home}/ant-contrib-1.0b3.jar"/>
    <property name="project.original.dir" location="original_project"/>
    <property name="project.instrumented.dir" location="instr_project"/>
    <property name="project.clover.db" location="${project.instrumented.dir}/.clover/clover.db"/>

    <taskdef resource="cloverlib.xml" classpath="${clover.jar}"/>
    <taskdef resource="net/sf/antcontrib/antlib.xml" classpath="${ant-contrib.jar}"/>

    <target name="_instrument-dir">
        <!-- Use double-slash for windows paths -->
        <propertyregex property="original.dir.quoted" input="${project.original.dir}" regexp="\\" replace="\\\\\\\\" global="true"/>
        <propertyregex property="relative.dir" input="${source.dir}" regexp="${original.dir.quoted}(.*)" select="\1"/>
        <echo message="Instrumenting ${source.dir} into ${project.instrumented.dir}${relative.dir}"/>
        <echo message="Clover database is ${project.clover.db}"/>
        <clover-instr destdir="${project.instrumented.dir}${relative.dir}" initstring="${project.clover.db}">
            <fileset dir="${project.original.dir}${relative.dir}">
                <include name="**/*.java"/>
            </fileset>
        </clover-instr>
    </target>

    <target name="instrument">
        <!-- Cleanup from previous run -->
        <delete dir="${project.instrumented.dir}"/>
        <!-- Find all source directories, for each of them call clover-instr. Please note that we cannot use sth like:
             <clover-instr srcdir="${project.original.dir}" destdir="${project.instrumented.dir}" initstring="${project.clover.db}">
             directly, because clover-instr does not recreate original directory structure, but puts everything
             under one destdir root.
         -->
        <foreach target="_instrument-dir" param="source.dir" inheritall="true" inheritrefs="true">
            <path>
                <!-- Define all package roots here -->
                <dirset dir="${project.original.dir}">
                    <include name="**/src"/>
                    <include name="**/test"/>
                </dirset>
            </path>
        </foreach>

        <!-- Copy all other non-java files as well -->
        <echo message="Copying other files from ${project.original.dir} to ${project.instrumented.dir}"/>
        <copy todir="${project.instrumented.dir}">
            <fileset dir="${project.original.dir}">
                <exclude name="**/*.java"/>
            </fileset>
        </copy>

        <!-- Now we can build it under Tycho. Don't even try to read instrumented sources ;-) -->
        <echo message="INSTRUMENTATION DONE. Run Maven build in ${project.instrumented.dir}"/>
    </target>

    <target name="report">
        <clover-report initstring="${project.clover.db}">
           <current outfile="current.html">
              <format type="html"/>
           </current>
           <current outfile="current.xml">
              <format type="xml"/>
           </current>
        </clover-report>
    </target>
</project>

 

Modified top-level pom.xml

You must have the Clover artefact available during compilation by Tycho. Modify the tycho-compiler-plugin configuration and add org.openclover:clover to <extraClasspathElements> option.

If necessary, add also Clover dependency to tycho-surefire-plugin as JVM argument.

<build>
  <plugins>
    <plugin>
      <groupId>org.eclipse.tycho</groupId>
      <artifactId>tycho-compiler-plugin</artifactId>
      <version>0.15.0</version>
      <configuration>
        <extraClasspathElements>
          <!-- Use the same Clover version as for source instrumentation -->
          <dependency>
            <groupId>org.openclover</groupId>
            <artifactId>clover</artifactId>
            <version>4.2.0</version>
          </dependency>
        </extraClasspathElements>
      </configuration>          
    </plugin>
    <plugin>
      <groupId>org.eclipse.tycho</groupId>
      <artifactId>tycho-surefire-plugin</artifactId>
      <version>0.15.0</version>
      <configuration>
        <!-- Use the same Clover version as for source instrumentation -->
        <argLine>-Xbootclasspath/a:${user.home}/.m2/repository/com/atlassian/clover/clover/4.0.0/clover-4.0.0.jar</argLine>
      </configuration>          
    </plugin>
    ...
  </plugins>
</build>

 

Usage

Directory layout:

/original_project - Tycho project
    /pom.xml      - must contain 'org.openclover:clover' dependency for build and runtime/test
    /module1
       /src       - typical location of source folders in eclipse plug-ins
       /test
    /module2
/instr_project    - copy of 'original_project' with instrumented files created by build script
    /pom.xml      
    /module1
       /src
       /test
    /module2
/build.xml        - Ant build script from above

Commands:

ant instrument
cd instr_project
mvn install
cd ..
ant report