I added coverage test with cobertura and test the demo project built yesterday. Then I add Sonar Ant task in the ant script and saved test result into Sonar database.
The following is a standard build script(add junit-4.*.jar and cobertura.jar to $ANT_HOME/lib, in Ubuntu it is /usr/share/ant/lib):
<?xml version="1.0" encoding="UTF-8"?>
<project name="MyJavaProj" basedir="./" default="coverage_report">
<property name="build.dir" value="${basedir}/build" />
<target name="init">
<delete dir="${build.dir}"/>
<mkdir dir="${build.dir}"/>
</target>
<property name="src.dir" value="${basedir}/src" />
<property name="src.class.dir" value="${build.dir}/class" />
<target name="compile-src" depends="init">
<mkdir dir="${src.class.dir}"/>
<javac srcdir="${src.dir}" destdir="${src.class.dir}" encoding="UTF-8" debug="true"/>
</target>
<taskdef classpath="cobertura.jar" resource="tasks.properties" />
<property name="instrumented.class.dir" value="${build.dir}/instrumented-class" />
<property name="cobertura.data.file" value="${instrumented.class.dir}/cobertura.ser" />
<target name="instrument" depends="compile-src">
<cobertura-instrument datafile="${cobertura.data.file}" todir="${instrumented.class.dir}">
<fileset dir="${src.class.dir}">
<include name="**/*.class" />
</fileset>
</cobertura-instrument>
</target>
<property name="test.dir" value="${basedir}/test" />
<property name="test.class.dir" value="${build.dir}/test" />
<target name="compile-test" depends="instrument">
<mkdir dir="${test.class.dir}"/>
<javac srcdir="${test.dir}" destdir="${test.class.dir}">
<classpath>
<pathelement location="${instrumented.class.dir}"/>
<pathelement location="${src.class.dir}"/>
</classpath>
</javac>
</target>
<property name="unittest.report.dir" value="${build.dir}/unittest_report" />
<property name="lib.dir" value="${basedir}/lib" />
<target name="unittest" depends="compile-test">
<mkdir dir="${unittest.report.dir}"/>
<junit printsummary="yes" fork="yes">
<sysproperty key="net.sourceforge.cobertura.datafile" file="${cobertura.data.file}" />
<classpath>
<pathelement location="${instrumented.class.dir}"/>
<pathelement location="${src.class.dir}"/>
<pathelement location="${test.class.dir}"/>
<pathelement location="${src.dir}"/>
<path refid="lib.path"/>
</classpath>
<formatter type="xml"/>
<batchtest todir="${unittest.report.dir}" haltonerror="no">
<fileset dir="${test.dir}">
<include name="**/*.java" />
</fileset>
</batchtest>
</junit>
</target>
<property name="coverage.report.dir" value="${build.dir}/coverage_report" />
<target name="coverage-report" depends="unittest">
<cobertura-report datafile="${cobertura.data.file}" srcdir="${src.dir}" destdir="${coverage.report.dir}" format="xml" />
</target>
<property name="sonar.jdbc.url" value="jdbc:h2:tcp://localhost:9092/sonar" />
<property name="sonar.jdbc.username" value="sonar" />
<property name="sonar.jdbc.password" value="sonar" />
<property name="sonar.projectKey" value="com.doco.gif.MyModule" />
<property name="sonar.projectName" value="My Unit Test Project Demo" />
<property name="sonar.projectVersion" value="2.1" />
<property name="sonar.language" value="java" />
<property name="sonar.sources" value="src" />
<property name="sonar.tests" value="test" />
<property name="sonar.binaries" value="${src.class.dir},${test.class.dir},${build.instrument.dir}" />
<property name="sonar.dynamicAnalysis" value="reuseReports" />
<property name="sonar.surefire.reportsPath" value="${unittest.report.dir}" />
<property name="sonar.core.codeCoveragePlugin" value="cobertura" />
<property name="sonar.cobertura.reportPath" value="${coverage.report.dir}/coverage.xml" />
<target name="sonar" depends="coverage-report">
<taskdef uri="antlib:org.sonar.ant" resource="org/sonar/ant/antlib.xml">
<classpath path="/usr/share/ant/lib/sonar-ant-task-2.1.jar" />
</taskdef>
<sonar:sonar xmlns:sonar="antlib:org.sonar.ant" />
</target>
</project>
To run this script successfully:
-
Build a demo java project and put this script at project root;
-
Copy sonar-ant-task-2.1.jar and junit-4.11.jar to $ANT_HOME/lib;
-
Start Sonar server: $SONAR_HOME/bin/sonar.sh console;
-
Run this script: ant sonar;
Note
-
You have to add "sonar.core.codeCoveragePlugin" or coverage result can't be collected by Sonar. This is not mentioned in official documents Code Coverage by Unit Tests for Java Project;
-
Take care of the spelling: "sonar.surefire.reportsPath" while "sonar.cobertura.reportPath";
-
The "xmlns:sonar="antlib:org.sonar.ant" in "sonar:sonar" is necessary or the prefix "sonar" would be unbound;
-
If unit test results can't be collected by Sonar, try to specify "sonar.binaries" carefully as above shows;
-
The value of junit report path "sonar.surefire.reportsPath" is a directory (because there are lots of reports under this folder), while the value of cobertura report is a file, if sonar can not get junit or cobertura report, verify these settings;
-
If there are "class xxx is not accessible through the ClassLoader." in output of sonar task, there are two solutions:
-
Remove property "sonar.binaries", where Sonar will not check bytecode;
-
In case you want Sonar check bytecodes, add property "sonar.libraries" like follows: