integrating JaCoCo in sonar using Ant

Solution 1:

The following is an ANT build that is configured to run a junit unit test and use jacoco for code coverage reporting. The results are uploaded to Sonar and finally ivy is used to download 3rd party jars and manage classpaths.

Example

├── build.properties
├── build.xml
├── ivy.xml
└── src
    ├── main
    │   └── java
    │       └── org
    │           └── demo
    │               └── App.java
    └── test
        └── java
            └── org
                └── demo
                    └── AppTest.java

build.properties

# Build properties
build.dir=build

src.dir=src/main/java
test.src.dir=src/test/java

classes.dir=${build.dir}/classes
test.classes.dir=${build.dir}/test-classes

reports.dir=${build.dir}/reports

# Sonar properties
sonar.projectKey=org.demo:demo
sonar.projectName=Demo project
sonar.projectVersion=1.0
sonar.projectDescription=This is my demo Sonar project

sonar.host.url=http://localhost:9000

sonar.jdbc.url=jdbc:h2:tcp://localhost:9092/sonar
sonar.jdbc.driverClassName=org.h2.Driver
sonar.jdbc.username=sonar
sonar.jdbc.password=sonar

sonar.working.directory=${build.dir}/sonar

sonar.language=java
sonar.sources=${src.dir}
sonar.binaries=${classes.dir}
sonar.tests=${test.src.dir}

sonar.dynamicAnalysis=reuseReports
sonar.surefire.reportsPath=${reports.dir}/junit
sonar.java.coveragePlugin=jacoco
sonar.jacoco.reportPath=${build.dir}/jacoco.exec

build.xml

<project name="demo" default="test" xmlns:ivy="antlib:org.apache.ivy.ant">

    <property file="build.properties"/>

    <target name="bootstrap" description="Install ivy">
        <mkdir dir="${user.home}/.ant/lib"/>
        <get dest="${user.home}/.ant/lib/ivy.jar" src="http://search.maven.org/remotecontent?filepath=org/apache/ivy/ivy/2.3.0/ivy-2.3.0.jar"/>
    </target>

    <target name="resolve" description="Download dependencies and setup classpaths">
        <ivy:resolve/>
        <ivy:report todir='${reports.dir}/ivy' graph='false' xml='false'/>

        <ivy:cachepath pathid="compile.path" conf="compile"/>
        <ivy:cachepath pathid="test.path"    conf="test"/>
        <ivy:cachepath pathid="build.path"   conf="build"/>
    </target>

    <target name="init" depends="resolve" description="Create build directories">
        <mkdir dir="${classes.dir}"/>
        <mkdir dir="${test.classes.dir}"/>
        <mkdir dir="${reports.dir}/junit"/>
    </target>

    <target name="compile" depends="init" description="Compile source code">
        <javac srcdir="${src.dir}" destdir="${classes.dir}" includeantruntime="false" debug="true" classpathref="compile.path"/>
    </target>

    <target name="compile-tests" depends="compile" description="Compile test source code">
        <javac srcdir="${test.src.dir}" destdir="${test.classes.dir}" includeantruntime="false" debug="true">
            <classpath>
                <path refid="test.path"/>
                <pathelement path="${classes.dir}"/>
            </classpath>
        </javac>
    </target>

    <target name="test" depends="compile-tests" description="Run unit tests and code coverage reporting">
        <taskdef uri="antlib:org.jacoco.ant" resource="org/jacoco/ant/antlib.xml" classpathref="build.path"/>

        <jacoco:coverage destfile="${build.dir}/jacoco.exec" xmlns:jacoco="antlib:org.jacoco.ant">
            <junit haltonfailure="yes" fork="true">
                <classpath>
                    <path refid="test.path"/>
                    <pathelement path="${classes.dir}"/>
                    <pathelement path="${test.classes.dir}"/>
                </classpath>
                <formatter type="plain" usefile="false" />
                <formatter type="xml"/>
                <batchtest fork="yes" todir="${reports.dir}/junit">
                    <fileset dir="${test.src.dir}">
                        <include name="**/*Test*.java"/>
                        <exclude name="**/AllTests.java"/>
                    </fileset>
                </batchtest>
            </junit>
        </jacoco:coverage>
    </target>

    <target name="sonar" depends="test" description="Upload metrics to Sonar">
        <taskdef uri="antlib:org.sonar.ant" resource="org/sonar/ant/antlib.xml" classpathref="build.path"/>

        <ivy:cachepath pathid="sonar.libraries" conf="compile"/> 

        <sonar:sonar xmlns:sonar="antlib:org.sonar.ant"/>
    </target>

    <target name="clean" description="Cleanup build files">
        <delete dir="${build.dir}"/>
    </target>

    <target name="clean-all" depends="clean" description="Additionally purge ivy cache">
        <ivy:cleancache/>
    </target>

</project>

ivy.xml

<ivy-module version="2.0">
    <info organisation="com.myspotontheweb" module="demo"/>

    <configurations defaultconfmapping="compile->default">
        <conf name="compile" description="Required to compile application"/>
        <conf name="test"    description="Required for test only" extends="compile"/>
        <conf name="build"   description="Build dependencies"/>
    </configurations>

    <dependencies>
        <!-- compile dependencies -->

        <!-- test dependencies -->
        <dependency org="junit" name="junit" rev="4.10" conf="test->default"/>

        <!-- build dependencies -->
        <dependency org="org.codehaus.sonar-plugins" name="sonar-ant-task" rev="2.1" conf="build->default"/>
        <dependency org="org.jacoco" name="org.jacoco.ant" rev="0.6.3.201306030806" conf="build->default"/>

        <!-- Global exclusions -->
        <exclude org="org.apache.ant"/>
    </dependencies>

</ivy-module>