I am trying to understand how JaCoCo and Sonar work together using the sonar ut-ant-jacoco-runTests example: https://github.com/SonarSource/sonar-examples/blob/master/projects/code-coverage/ut/ant/ut-ant-jacoco-runTests/build.xml
<?xml version="1.0" encoding="UTF-8"?>
<project name="UT coverage with Ant and JaCoCo running tests" default="all" basedir="." xmlns:sonar="antlib:org.sonar.ant">
<!-- ========= Define the main properties of this project ========= -->
<property name="src.dir" value="src" />
<property name="test.dir" value="test" />
<property name="lib.junit.dir" value="lib" />
<property name="build.dir" value="target" />
<property name="classes.dir" value="${build.dir}/classes" />
<property name="reports.dir" value="${build.dir}/reports" />
<property name="reports.junit.xml.dir" value="${reports.dir}/junit" />
<!-- Define the SonarQube properties -->
<property name="sonar.projectKey" value="org.codehaus.sonar:example-ut-ant-jacoco-runTests" />
<property name="sonar.projectName" value="UT coverage with Ant and JaCoCo running tests" />
<property name="sonar.projectVersion" value="1.0" />
<property name="sonar.language" value="java" />
<property name="sonar.sources" value="${src.dir}" />
<property name="sonar.tests" value="${test.dir}" />
<property name="sonar.binaries" value="${classes.dir}" />
<property name="sonar.sourceEncoding" value="UTF-8" />
<property name="sonar.junit.reportsPath" value="${reports.junit.xml.dir}" />
<!-- The following properties are required to use JaCoCo: -->
<property name="sonar.dynamicAnalysis" value="reuseReports" />
<property name="sonar.java.coveragePlugin" value="jacoco" />
<property name="sonar.jacoco.reportPath" value="target/jacoco.exec" />
<!-- Add your basic SonarQube configuration below: sonar.jdbc.url, sonar.jdbc.username, etc. properties -->
<!--
<property name="sonar.jdbc.url" value="jdbc:..." />
<property name="sonar.jdbc.username" value="..." />
<property name="sonar.jdbc.password" value="..." />
-->
<!-- ========= Define "regular" targets: clean, compile, test, ... ========= -->
<target name="clean">
<delete dir=".sonar" />
<delete dir="${build.dir}" />
<delete dir="${reports.dir}" />
</target>
<target name="init">
<mkdir dir="${build.dir}" />
<mkdir dir="${classes.dir}" />
<mkdir dir="${reports.dir}" />
<mkdir dir="${reports.junit.xml.dir}" />
</target>
<target name="compile" depends="init">
<javac srcdir="${src.dir}" destdir="${classes.dir}" classpathref="classpath" fork="true" debug="true" includeAntRuntime="false" />
<javac srcdir="${test.dir}" destdir="${classes.dir}" classpathref="classpath" fork="true" debug="true" includeAntRuntime="false" />
</target>
<path id="classpath">
<fileset dir="${lib.junit.dir}" includes="*.jar"/>
</path>
<target name="test" depends="compile">
<taskdef name="junit" classname="org.apache.tools.ant.taskdefs.optional.junit.JUnitTask">
<classpath>
<path refid="classpath"/>
</classpath>
</taskdef>
<!-- Import the JaCoCo Ant Task -->
<taskdef uri="antlib:org.jacoco.ant" resource="org/jacoco/ant/antlib.xml">
<!-- Update the following line, or put the "jacocoant.jar" file in your "$HOME/.ant/lib" folder -->
<classpath path="path/to/jacoco/ant/task/lib/jacocoant.jar" />
</taskdef>
<!-- Run your unit tests, adding the JaCoCo agent -->
<jacoco:coverage destfile="target/jacoco.exec" xmlns:jacoco="antlib:org.jacoco.ant">
<junit fork="yes" dir="${basedir}" failureProperty="test.failed">
<classpath location="${classes.dir}" />
<classpath refid="classpath" />
<formatter type="xml" />
<batchtest todir="${reports.junit.xml.dir}">
<fileset dir="${test.dir}">
<include name="**/*Test.java" />
</fileset>
</batchtest>
</junit>
</jacoco:coverage>
</target>
<!-- ========= Define SonarQube target ========= -->
<target name="sonar" depends="compile">
<taskdef uri="antlib:org.sonar.ant" resource="org/sonar/ant/antlib.xml">
<!-- Update the following line, or put the "sonar-ant-task-*.jar" file in your "$HOME/.ant/lib" folder -->
<classpath path="path/to/sonar/ant/task/lib/sonar-ant-task-*.jar" />
</taskdef>
<!-- Execute SonarQube -->
<sonar:sonar />
</target>
<!-- ========= The main target "all" ========= -->
<target name="all" depends="clean,compile,test,sonar" />
</project>
I install sonar in my local machines, default configuration.
then I run the example as follows:
$ git clone https://github.com/SonarSource/sonar-examples.git
$ cd sonar-examples/projects/code-coverage/ut/ant/ut-ant-jacoco-runTests
# get the two missing libraries:
$ wget http://repository.codehaus.org/org/codehaus/sonar-plugins/sonar-ant-task/2.1/sonar-ant-task-2.1.jar
$ wget -Ojacoco-0.6.4.201312101107.zip http://search.maven.org/remotecontent?filepath=org/jacoco/jacoco/0.6.4.201312101107/jacoco-0.6.4.201312101107.zip
$ unzip -p jacoco-0.6.4.201312101107.zip lib/jacocoant.jar >jacocoanto-0.6.4.201312101107.jar
#edit build.xml and replace:
<classpath path="path/to/jacoco/ant/task/lib/jacocoant.jar" />
<classpath path="path/to/sonar/ant/task/lib/sonar-ant-task-*.jar" />
by
<classpath path="./jacocoanto-0.6.4.201312101107.jar" />
<classpath path="./sonar-ant-task-2.1.jar" />
$ ant clean compile
# this creates:
./target/classes/One.class
./target/classes/OneTest.class
$ ant test
[jacoco:coverage] Enhancing junit with coverage
[junit] objc[50244]: Class JavaLaunchHelper is implemented in both /Library/Java/JavaVirtualMachines/jdk1.7.0_40.jdk/Contents/Home/jre/bin/java and /Library/Java/JavaVirtualMachines/jdk1.7.0_40.jdk/Contents/Home/jre/lib/libinstrument.dylib. One of the two will be used. Which one is undefined.
# Why I get this warning? is there something misconfigured?
# this creates:
./target/jacoco.exec
./target/reports/junit/TEST-OneTest.xml
$ ant sonar
# this generates these two files, which are just a list of pmd rules (taken from the local sonar installation I guess). in any case, they are not a computation result.
.sonar//pmd-unit-tests.xml
.sonar//pmd.xml
# and sends the results to sonar.
with Unit tests success: 100% (1 tests), Unit Tests coverage: 60.0%
so, how do JaCoCo and Sonar work together?
what does JaCoCo do exactly?
what does this ./target/jacoco.exec file contain exactly?
how does Sonar use this file, and what does Sonar do exactly?
where is the 60.00% coverage result computed? during ant test or during ant sonar?
Full log of ant sonar:
$ ant sonar
Buildfile: /private/tmp/aa/sonar-examples/projects/code-coverage/ut/ant/ut-ant-jacoco-runTests/build.xml
init:
compile:
sonar:
[sonar:sonar] Apache Ant(TM) version 1.9.3 compiled on December 23 2013
[sonar:sonar] Sonar Ant Task version: 2.1
[sonar:sonar] Loaded from: file:/private/tmp/aa/sonar-examples/projects/code-coverage/ut/ant/ut-ant-jacoco-runTests/sonar-ant-task-2.1.jar
[sonar:sonar] INFO: Default locale: "en_US", source code encoding: "UTF-8"
[sonar:sonar] INFO: Work directory: /private/tmp/aa/sonar-examples/projects/code-coverage/ut/ant/ut-ant-jacoco-runTests/.sonar
[sonar:sonar] INFO: Sonar Server 4.0
[sonar:sonar] 15:49:08.182 INFO - Load batch settings
[sonar:sonar] 15:49:08.259 INFO - User cache: /Users/david/.sonar/cache
[sonar:sonar] 15:49:08.266 INFO - Install plugins
[sonar:sonar] 15:49:08.523 INFO - Install JDBC driver
[sonar:sonar] 15:49:08.529 WARN - H2 database should be used for evaluation purpose only
[sonar:sonar] 15:49:08.529 INFO - Create JDBC datasource for jdbc:h2:tcp://localhost/sonar
[sonar:sonar] 15:49:09.365 INFO - Initializing Hibernate
[sonar:sonar] 15:49:11.269 INFO - Load project settings
[sonar:sonar] 15:49:11.293 INFO - Apply project exclusions
[sonar:sonar] 15:49:11.405 INFO - ------------- Scan UT coverage with Ant and JaCoCo running tests
[sonar:sonar] 15:49:11.408 INFO - Load module settings
[sonar:sonar] 15:49:11.732 INFO - Quality profile : [name=Sonar way,language=java]
[sonar:sonar] 15:49:11.744 INFO - Excluded tests:
[sonar:sonar] 15:49:11.744 INFO - **/package-info.java
[sonar:sonar] 15:49:11.809 INFO - Index files
[sonar:sonar] 15:49:11.827 INFO - 2 files indexed
[sonar:sonar] 15:49:11.836 INFO - Loading technical debt model...
[sonar:sonar] 15:49:12.599 INFO - Loading technical debt model done: 763 ms
[sonar:sonar] 15:49:12.615 INFO - Configure Maven plugins
[sonar:sonar] 15:49:12.975 INFO - Compare to previous analysis (2014-01-20)
[sonar:sonar] 15:49:12.990 INFO - Compare over 30 days (2013-12-21, analysis of 2014-01-16 12:11:07.227)
[sonar:sonar] 15:49:13.142 INFO - Base dir: /private/tmp/aa/sonar-examples/projects/code-coverage/ut/ant/ut-ant-jacoco-runTests
[sonar:sonar] 15:49:13.142 INFO - Working dir: /private/tmp/aa/sonar-examples/projects/code-coverage/ut/ant/ut-ant-jacoco-runTests/.sonar
[sonar:sonar] 15:49:13.143 INFO - Source dirs: /private/tmp/aa/sonar-examples/projects/code-coverage/ut/ant/ut-ant-jacoco-runTests/src
[sonar:sonar] 15:49:13.143 INFO - Test dirs: /private/tmp/aa/sonar-examples/projects/code-coverage/ut/ant/ut-ant-jacoco-runTests/test
[sonar:sonar] 15:49:13.143 INFO - Binary dirs: /private/tmp/aa/sonar-examples/projects/code-coverage/ut/ant/ut-ant-jacoco-runTests/target/classes
[sonar:sonar] 15:49:13.143 INFO - Source encoding: UTF-8, default locale: en_US
[sonar:sonar] 15:49:13.152 INFO - Sensor JavaSourceImporter...
[sonar:sonar] 15:49:13.171 INFO - Sensor JavaSourceImporter done: 19 ms
[sonar:sonar] 15:49:13.171 INFO - Sensor JavaSquidSensor...
[sonar:sonar] 15:49:13.237 INFO - Java AST scan...
[sonar:sonar] 15:49:13.242 INFO - 1 source files to be analyzed
[sonar:sonar] 15:49:13.347 INFO - 1/1 source files analyzed
[sonar:sonar] 15:49:13.348 INFO - Java AST scan done: 111 ms
[sonar:sonar] 15:49:13.350 INFO - Java bytecode scan...
[sonar:sonar] 15:49:13.374 INFO - Java bytecode scan done: 24 ms
[sonar:sonar] 15:49:13.383 INFO - Package design analysis...
[sonar:sonar] 15:49:13.394 INFO - Package design analysis done: 11 ms
[sonar:sonar] 15:49:13.399 INFO - Sensor JavaSquidSensor done: 228 ms
[sonar:sonar] 15:49:13.399 INFO - Sensor SurefireSensor...
[sonar:sonar] 15:49:13.400 INFO - parsing /private/tmp/aa/sonar-examples/projects/code-coverage/ut/ant/ut-ant-jacoco-runTests/target/reports/junit
[sonar:sonar] 15:49:13.464 INFO - Sensor SurefireSensor done: 65 ms
[sonar:sonar] 15:49:13.464 INFO - Sensor CpdSensor...
[sonar:sonar] 15:49:13.464 INFO - SonarEngine is used
[sonar:sonar] 15:49:13.465 INFO - Cross-project analysis disabled
[sonar:sonar] 15:49:13.483 INFO - Sensor CpdSensor done: 19 ms
[sonar:sonar] 15:49:13.483 INFO - Sensor PmdSensor...
[sonar:sonar] 15:49:13.484 INFO - Execute PMD 4.3...
[sonar:sonar] 15:49:13.492 INFO - Java version: 1.5
[sonar:sonar] 15:49:13.512 INFO - PMD configuration: /private/tmp/aa/sonar-examples/projects/code-coverage/ut/ant/ut-ant-jacoco-runTests/.sonar/pmd.xml
[sonar:sonar] 15:49:14.061 INFO - PMD configuration: /private/tmp/aa/sonar-examples/projects/code-coverage/ut/ant/ut-ant-jacoco-runTests/.sonar/pmd-unit-tests.xml
[sonar:sonar] 15:49:14.062 INFO - Execute PMD 4.3 done: 578 ms
[sonar:sonar] 15:49:14.062 INFO - Sensor PmdSensor done: 579 ms
[sonar:sonar] 15:49:14.062 INFO - Sensor InitialOpenIssuesSensor...
[sonar:sonar] 15:49:14.070 INFO - Sensor InitialOpenIssuesSensor done: 8 ms
[sonar:sonar] 15:49:14.071 INFO - Sensor ProfileSensor...
[sonar:sonar] 15:49:14.175 INFO - Sensor ProfileSensor done: 104 ms
[sonar:sonar] 15:49:14.175 INFO - Sensor ProfileEventsSensor...
[sonar:sonar] 15:49:14.194 INFO - Sensor ProfileEventsSensor done: 19 ms
[sonar:sonar] 15:49:14.195 INFO - Sensor ProjectLinksSensor...
[sonar:sonar] 15:49:14.201 INFO - Sensor ProjectLinksSensor done: 6 ms
[sonar:sonar] 15:49:14.201 INFO - Sensor VersionEventsSensor...
[sonar:sonar] 15:49:14.213 INFO - Sensor VersionEventsSensor done: 12 ms
[sonar:sonar] 15:49:14.214 INFO - Sensor FileHashSensor...
[sonar:sonar] 15:49:14.215 INFO - Sensor FileHashSensor done: 1 ms
[sonar:sonar] 15:49:14.215 INFO - Sensor JaCoCoSensor...
[sonar:sonar] 15:49:14.220 INFO - Analysing /private/tmp/aa/sonar-examples/projects/code-coverage/ut/ant/ut-ant-jacoco-runTests/target/jacoco.exec
[sonar:sonar] 15:49:14.289 INFO - No information about coverage per test.
[sonar:sonar] 15:49:14.289 INFO - Sensor JaCoCoSensor done: 74 ms
[sonar:sonar] 15:49:14.794 INFO - Execute decorators...
[sonar:sonar] 15:49:15.196 INFO - Store results in database
[sonar:sonar] 15:49:15.238 INFO - ANALYSIS SUCCESSFUL, you can browse http://localhost:9000/dashboard/index/org.codehaus.sonar:example-ut-ant-jacoco-runTests
[sonar:sonar] 15:49:15.263 INFO - Executing post-job class org.sonar.plugins.core.issue.notification.SendIssueNotificationsPostJob
[sonar:sonar] 15:49:15.264 INFO - Executing post-job class org.sonar.plugins.core.batch.IndexProjectPostJob
[sonar:sonar] 15:49:15.284 INFO - Executing post-job class org.sonar.plugins.dbcleaner.ProjectPurgePostJob
[sonar:sonar] 15:49:15.295 INFO - -> Keep one snapshot per day between 2013-12-23 and 2014-01-19
[sonar:sonar] 15:49:15.296 INFO - -> Keep one snapshot per week between 2013-01-21 and 2013-12-23
[sonar:sonar] 15:49:15.297 INFO - -> Keep one snapshot per month between 2009-01-26 and 2013-01-21
[sonar:sonar] 15:49:15.297 INFO - -> Delete data prior to: 2009-01-26
[sonar:sonar] 15:49:15.299 INFO - -> Clean UT coverage with Ant and JaCoCo running tests [id=1018]
[sonar:sonar] 15:49:15.303 INFO - <- Clean snapshot 18068
JaCoCo is used during the <junit/> task itself. When executed, JaCoCo instruments the class files used in the test with the coverage information. This produces a jacaco.exec file. This file is then used to generate the code coverage report.
There's usually a <jacoco:report/> task that takes the jacoco.exec file and generates either a text file, a HTML page, or an XML file with the coverage information in it. This is probably what Sonar uses for its analysis.
Of course, it's hard without seeing the build.xml file how things work.
Related
I'm integrating the sonar for my ant build. And i add the below properties in my file.
I'm using SonarQube 4.3.3 with Sonar-ant-task 2.2.jar.
I'm using Jenkins to make the build.
<project name="system_make" default="all" basedir="." xmlns:sonar="antlib:org.sonar.ant" >
<target name="sonar">
<property name="sonar.jdbc.url" value="${JDBC_URL}>" />
<property name="sonar.jdbc.username" value="PROD_SONAR_43" />
<property name="sonar.jdbc.password" value="{aes}gLq2TqprrkJTNsTn8O6QKQ==" />
<property name="sonar.secretKeyPath" value="/app2/team/xxx/secretkey.txt " />
<property name="sonar.host.url" value="http://<IP>/9000" />
<property name="sonar.projectKey" value="YYYY:ZZZZ" />
<property name="sonar.projectVersion" value="1.0" />
<property name="sonar.language" value="java" />
<property name="sonar.sources" value="src" />
<taskdef uri="antlib:org.sonar.ant" resource="org/sonar/ant/antlib.xml">
<classpath path="/app2/team/SonarQube4.3.3_Prod/sonarqube-4.3.3/lib/sonar-ant-task-2.2.jar" />
</taskdef>
<sonar:sonar />
</target>
while i running the build i'm getting the below exception.
Please let me know the solution for the above error.
sonar:
[sonar:sonar] Apache Ant version 1.6.5 compiled on June 2 2005
[sonar:sonar] SonarQube Ant Task version: 2.2
[sonar:sonar] Loaded from: file:/app2/buildteam/SonarQube4.3.3_Prod/sonarqube-4.3.3/lib/sonar-ant-task-2.2.jar
[sonar:sonar] INFO: Default locale: "en_US", source code encoding: "UTF-8" (analysis is platform dependent)
[sonar:sonar] INFO: Work directory: /app2/buildteam/.jenkins/jobs/MI-Cloud Migration/.sonar
[sonar:sonar] INFO: SonarQube Server 4.3.3
BUILD FAILED
/app2/buildteam/.jenkins/jobs/MI-Cloud Migration/system_make.xml:32: org.sonar.runner.impl.RunnerException: Unable to execute Sonar.
I have very simple Sonar configuration with Ant task:
<target name="upload_to_sonar">
<property name="sonar.jdbc.url" value="jdbc:oracle:thin:#server:1521:sid"/>
<property name="sonar.host.url" value="http://sonar:80"/>
<property name="sonar.jdbc.username" value="SONAR"/>
<property name="sonar.jdbc.password" value="SONAR"/>
<property name="sonar.projectKey" value="test"/>
<property name="sonar.projectName" value="test"/>
<property name="sonar.projectVersion" value="trunk"/>
<property name="sonar.language" value="java"/>
<property name="sonar.sources" value="sources_for_sonar"/>
<property name="sonar.binaries" value="classes_for_sonar"/>
<taskdef name="sonar" classname="org.sonar.ant.SonarTask">
<classpath path="${EXTERNAL}/sonar-ant-task-2.0.jar" />
</taskdef>
<sonar/>
</target>
Those folders contain sources and classes in root level.
For some reason execution gives me following error no matter how I configure it:
Buildfile: D:\trunk\src\build.xml
upload_to_sonar:
[sonar:sonar] Apache Ant(TM) version 1.8.2 compiled on December 20 2010
[sonar:sonar] Sonar Ant Task version: 2.0
[sonar:sonar] Loaded from: file:/D:/trunk/src/./sources/external/sonar-ant-task-
2.0.jar
[sonar:sonar] Sonar work directory: D:\trunk\src\.sonar
[sonar:sonar] Sonar server: http://sonar:80
BUILD FAILED
D:\trunk\src\build.xml:132: org.sonar.runner.RunnerException: java.lang.IllegalS
tateException: Infinite loop in property interpolation of ${SQLSCRIPT}: SQLSCRIP
T
at org.sonar.runner.Runner.delegateExecution(Runner.java:288)
at org.sonar.runner.Runner.execute(Runner.java:151)
at org.sonar.ant.SonarTask.launchAnalysis(SonarTask.java:93)
at org.sonar.ant.SonarTask.execute(SonarTask.java:75)
at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:291)
at sun.reflect.GeneratedMethodAccessor4.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
sorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.jav
a:106)
at org.apache.tools.ant.Task.perform(Task.java:348)
at org.apache.tools.ant.Target.execute(Target.java:390)
at org.apache.tools.ant.Target.performTasks(Target.java:411)
at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1399)
at org.apache.tools.ant.Project.executeTarget(Project.java:1368)
at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExe
cutor.java:41)
at org.apache.tools.ant.Project.executeTargets(Project.java:1251)
at org.apache.tools.ant.Main.runBuild(Main.java:809)
at org.apache.tools.ant.Main.startAnt(Main.java:217)
at org.apache.tools.ant.launch.Launcher.run(Launcher.java:280)
at org.apache.tools.ant.launch.Launcher.main(Launcher.java:109)
Caused by: java.lang.IllegalStateException: Infinite loop in property interpolat
ion of ${SQLSCRIPT}: SQLSCRIPT
at org.apache.commons.lang.text.StrSubstitutor.checkCyclicSubstitution(S
trSubstitutor.java:701)
at org.apache.commons.lang.text.StrSubstitutor.substitute(StrSubstitutor
.java:645)
at org.apache.commons.lang.text.StrSubstitutor.substitute(StrSubstitutor
.java:656)
at org.apache.commons.lang.text.StrSubstitutor.substitute(StrSubstitutor
.java:563)
at org.apache.commons.lang.text.StrSubstitutor.replace(StrSubstitutor.ja
va:305)
at org.apache.commons.configuration.PropertyConverter.interpolate(Proper
tyConverter.java:958)
at org.apache.commons.configuration.AbstractConfiguration.interpolate(Ab
stractConfiguration.java:446)
at org.apache.commons.configuration.CompositeConfiguration.getList(Compo
siteConfiguration.java:312)
at org.apache.commons.configuration.AbstractConfiguration.getList(Abstra
ctConfiguration.java:1109)
at org.apache.commons.configuration.CompositeConfiguration.getStringArra
y(CompositeConfiguration.java:320)
at org.sonar.batch.Batch.convertToProperties(Batch.java:89)
at org.sonar.batch.Batch.create(Batch.java:78)
at org.sonar.runner.internal.batch.Launcher.executeBatch(Launcher.java:6
8)
at org.sonar.runner.internal.batch.Launcher.execute(Launcher.java:61)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
sorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.sonar.runner.Runner.delegateExecution(Runner.java:285)
... 19 more
Total time: 1 minute 12 seconds
SONAR server version is 3.2
Ant task version 2.0
Enabling verbosity don't give any additional details whatsoever
Created a ticket for community http://jira.codehaus.org/browse/SONARPLUGINS-2704
I'm trying to following apache's ANT tutorial:
http://ant.apache.org/manual/index.html
I'm currently at the JUnit portion, but I keep getting errors related to not being able to find the junit.framework package.
I believe I've followed the tutorial exactly as follows - Here are the details:
-----My file structure-----
build.xml
/build
../classes
/lib
..log4j-1.2.8.jar
myManifest
/src
..HelloWorldTest.java
..log4j.properties
../oata
....HelloWorld.java
-----Sources-----
myManifest:
Main-Class: oata.HelloWorld
build.xml:
<project name ="HelloWorld" basedir="." default="main">
<property name="src.dir" value="src" />
<property name="build.dir" value="build" />
<property name="classes.dir" value="${build.dir}/classes" />
<property name="jar.dir" value="${build.dir}/jar" />
<property name="lib.dir" value="lib" />
<path id="classpath">
<fileset dir="${lib.dir}" includes="**/*.jar" />
</path>
<property name="main-class" value="oata.HelloWorld" />
<target name="clean">
<delete dir="${build.dir}"/>
</target>
<target name="compile">
<mkdir dir="${classes.dir}"/>
<javac srcdir="${src.dir}" destdir="${classes.dir}" classpathref="classpath" />
<copy todir="${classes.dir}" >
<fileset dir="${src.dir}" excludes="**/*.java" />
</copy>
</target>
<target name="jar" depends="compile">
<mkdir dir="${jar.dir}" />
<jar destfile="${jar.dir}/${ant.project.name}.jar" basedir="${classes.dir}">
<manifest>
<attribute name="Main-Class" value="${main-class}" />
</manifest>
</jar>
</target>
<target name="run" depends="jar">
<java fork="true" classname="${main-class}">
<classpath>
<path refid="classpath"/>
<path id="application" location="${jar.dir}/${ant.project.name}.jar"/>
</classpath>
</java>
</target>
<target name="junit" depends="jar">
<junit printsummary="yes">
<classpath>
<path refid="classpath"/>
<path refid="application"/>
</classpath>
<batchtest fork="yes">
<fileset dir="${src.dir}" includes="*Test.java"/>
</batchtest>
</junit>
</target>
<target name="clean-build" depends="clean,jar" />
<target name="main" depends="clean,run" />
</project>
HelloWorldTest.java:
public class HelloWorldTest extends junit.framework.TestCase {
public void testNothing() {
}
public void testWillAlwaysFail() {
fail("An error message");
}
}
HelloWorld.java
package oata;
import org.apache.log4j.Logger;
public class HelloWorld {
static Logger logger = Logger.getLogger(HelloWorld.class);
public static void main(String [] args){
logger.info("Hello World!");
}
}
log4j.properties:
log4j.rootLogger=DEBUG, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%m%n
---Output---
ant -verbose junit
Apache Ant(TM) version 1.8.2 compiled on June 20 2012
Trying the default build file: build.xml
Buildfile: /Users/jtyler/Projects/AntHelloWorld/build.xml
Detected Java version: 1.6 in: /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home
Detected OS: Mac OS X
parsing buildfile /Users/jtyler/Projects/AntHelloWorld/build.xml with URI = file:/Users/jtyler/Projects/AntHelloWorld/build.xml
Project base dir set to: /Users/jtyler/Projects/AntHelloWorld
parsing buildfile jar:file:/usr/share/ant/lib/ant.jar!/org/apache/tools/ant/antlib.xml with URI = jar:file:/usr/share/ant/lib/ant.jar!/org/apache/tools/ant/antlib.xml from a zip file
Build sequence for target(s) `junit' is [compile, jar, junit]
Complete build sequence is [compile, jar, junit, clean, run, main, clean-build, ]
compile:
[mkdir] Skipping /Users/jtyler/Projects/AntHelloWorld/build/classes because it already exists.
[javac] /Users/jtyler/Projects/AntHelloWorld/build.xml:20: warning: 'includeantruntime' was not set, defaulting to build.sysclasspath=last; set to false for repeatable builds
[javac] HelloWorldTest.java added as HelloWorldTest.class doesn't exist.
[javac] /Users/jtyler/Projects/AntHelloWorld/src/log4j.properties skipped - don't know how to handle it
[javac] oata/HelloWorld.java added as oata/HelloWorld.class doesn't exist.
[javac] Compiling 2 source files to /Users/jtyler/Projects/AntHelloWorld/build/classes
[javac] Using modern compiler
[javac] Compilation arguments:
[javac] '-d'
[javac] '/Users/jtyler/Projects/AntHelloWorld/build/classes'
[javac] '-classpath'
[javac] '/Users/jtyler/Projects/AntHelloWorld/build/classes:/Users/jtyler/Projects/AntHelloWorld/lib/log4j-1.2.8.jar:/usr/share/ant/lib/ant-launcher.jar:/usr/share/ant/lib/ant-antlr.jar:/usr/share/ant/lib/ant-jmf.jar:/usr/share/ant/lib/ant-junit.jar:/usr/share/ant/lib/ant-junit4.jar:/usr/share/ant/lib/ant-swing.jar:/usr/share/ant/lib/ant-testutil.jar:/usr/share/ant/lib/ant.jar'
[javac] '-sourcepath'
[javac] '/Users/jtyler/Projects/AntHelloWorld/src'
[javac] '-g:none'
[javac]
[javac] The ' characters around the executable and arguments are
[javac] not part of the command.
[javac] Files to be compiled:
[javac] /Users/jtyler/Projects/AntHelloWorld/src/HelloWorldTest.java
[javac] /Users/jtyler/Projects/AntHelloWorld/src/oata/HelloWorld.java
[javac] /Users/jtyler/Projects/AntHelloWorld/src/HelloWorldTest.java:1: package junit.framework does not exist
[javac] public class HelloWorldTest extends junit.framework.TestCase {
[javac] ^
[javac] /Users/jtyler/Projects/AntHelloWorld/src/HelloWorldTest.java:7: cannot find symbol
[javac] symbol : method fail(java.lang.String)
[javac] location: class HelloWorldTest
[javac] fail("An error message");
[javac] ^
[javac] 2 errors
BUILD FAILED
/Users/jtyler/Projects/AntHelloWorld/build.xml:20: Compile failed; see the compiler error output for details.
at org.apache.tools.ant.taskdefs.Javac.compile(Javac.java:1150)
at org.apache.tools.ant.taskdefs.Javac.execute(Javac.java:912)
at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:291)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
at org.apache.tools.ant.Task.perform(Task.java:348)
at org.apache.tools.ant.Target.execute(Target.java:390)
at org.apache.tools.ant.Target.performTasks(Target.java:411)
at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1399)
at org.apache.tools.ant.Project.executeTarget(Project.java:1368)
at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41)
at org.apache.tools.ant.Project.executeTargets(Project.java:1251)
at org.apache.tools.ant.Main.runBuild(Main.java:809)
at org.apache.tools.ant.Main.startAnt(Main.java:217)
at org.apache.tools.ant.launch.Launcher.run(Launcher.java:280)
at org.apache.tools.ant.launch.Launcher.main(Launcher.java:109)
Total time: 0 seconds
Is there something I'm missing that's needed to be included that was (or wasn't) mentioned in the tutorial?
EDIT: Based on Alex's inquiries, I tested to see if I had ant's junit jars in my shared directories (which I do):
$ ls /usr/share/ant/lib/ant-junit*.jar
/usr/share/ant/lib/ant-junit.jar /usr/share/ant/lib/ant-junit4.jar
I also tried to manually put ant-junit, ant-junit4.jar, and junit.jar into my project's lib directory, with the following results (all errors) after running ant clean junit:
junit.jar - /Users/jtyler/Projects/AntHelloWorld/build.xml:45: Reference application not found.
ant-junit.jar: package junit.framework does not exist
ant-junit.jar and ant.junit4.jar: package junit.framework does not exist
ant-junit4.jar: package junit.framework does not exist
EDIT The whole error when only junit.jar is included in the lib folder and calling ant clean junit is:
$ ant clean junit
Buildfile: /Users/jtyler/Projects/AntHelloWorld/build.xml
clean:
[delete] Deleting directory /Users/jtyler/Projects/AntHelloWorld/build
compile:
[mkdir] Created dir: /Users/jtyler/Projects/AntHelloWorld/build/classes
[javac] /Users/jtyler/Projects/AntHelloWorld/build.xml:20: warning: 'includeantruntime' was not set, defaulting to build.sysclasspath=last; set to false for repeatable builds
[javac] Compiling 2 source files to /Users/jtyler/Projects/AntHelloWorld/build/classes
[copy] Copying 1 file to /Users/jtyler/Projects/AntHelloWorld/build/classes
jar:
[mkdir] Created dir: /Users/jtyler/Projects/AntHelloWorld/build/jar
[jar] Building jar: /Users/jtyler/Projects/AntHelloWorld/build/jar/HelloWorld.jar
junit:
BUILD FAILED
/Users/jtyler/Projects/AntHelloWorld/build.xml:45: Reference application not found.
The tutorial is misleading. The junit files that are included in ant do not work. I downloaded juinit and copied the jar file to the lib folder of the project and it now works fine.
On top of including the junit.jar file within my lib dir, I added the following line to my build.xml file right above the junit task declaration:
<path id="application" location="${jar.dir}/${ant.project.name}.jar"/>
which is a copy of the 'application' path id declaration within the 'run' task definition.
The application builds successfully, and I get the following output with ant junit (test failure is expected):
ant junit
Buildfile: /Users/jtyler/Projects/AntHelloWorld/build.xml
compile:
[javac] /Users/jtyler/Projects/AntHelloWorld/build.xml:20: warning: 'includeantruntime' was not set, defaulting to build.sysclasspath=last; set to false for repeatable builds
jar:
junit:
[junit] Running HelloWorldTest
[junit] Tests run: 2, Failures: 1, Errors: 0, Time elapsed: 0.001 sec
[junit] Test HelloWorldTest FAILED
BUILD SUCCESSFUL
Total time: 1 second
Comments the following questions would be greatly appreciated:
Is the fact I actually needed to include the junit.jar file in my lib folder something I should be concerned about? I would assume this is not necessary if ant's tutorial explicitly states "Because Ant has a built-in JUnit 3.8.2 you could start directly using it."
Is the fact I needed to define the 'application' path id outside of the run task definition a typo within the apache ant tutorial? Or are there other things I missed or should consider?
Thanks to all those that helped.
You must specify junit.jar itself in your compile and in your <junit> task's classpath. This is not automatically included in your compile:
<!-- Contains junit.jar and other needed test classes -->
<path id="junit.classpath">
<fileset dir="${junit.directory}"/>
</path>
<!-- Contains third party jars your code is dependent upon -->
<path id="main.classpath">
<fileset dir="${dependent.jar.dir}"/>
</path>
<!-- Your main Java source code directory -->
<property name="main.srcdir" value="${basedir}/src/main/java"/>
<!-- Your main Junit test directory source code -->
<property name="test.srcdir" value="${basedir}/src/test/java"/>
<!-- Where you're compiling your main classes to -->
<property name="main.destdir" value="${basedir}/target/classes"/>
<!-- Where you're compiling your test classes to -->
<property name="test.destdir" value="${basedir}/target/test-classes"/>
[...]
<!-- Compile Test Classes -->
<!-- Notice you have three classpath elements:
* Your main classes you compiled before
* Your test main classpath that your main classes
were dependent up
* The junit.jar classpath
-->
<javac destdir="${test.destdir}"
srcdir="${test.srcdir}">
<classpath>
<!-- Your non-test classes you compiled before -->
<pathelement path="${main.destdir}/>
</classpath>
<classpath refid="junit.classpath"/>
<classpath refid="main.classpath"/>
</javac>
<!-- Now run your unit tests: Note how you have the same
three classpath elements as before -->
<junit fork="yes">
<classpath>
<pathelement path="${main.destdir}"/>
<pathelement path="${test.destdir}"/>
</classpath>
<classpath refid="main.classpath"/>
<classpath refid="junit.classpath"/>
[...]
</junit>
I had a working sonar/jenkins installation, where sonar was installed on localhost:9000 and jenkins was on localhost:8080. I then wanted to hide those services behind Apache and protect them behind Crowd-authenticated account access.
So first, I relocated Jenkins to localhost:8080/jenkins and proxied it. Which worked.
Then I relocated Sonar to localhost:9000/sonar and proxied it. Which also worked.
But now, when I try to execute the Sonar task from within the build script in Jenkins, I get the following error:
sonar:
[sonar:sonar] Apache Ant version 1.7.1 compiled on April 26 2010
[sonar:sonar] Sonar Ant Task version: 1.2
[sonar:sonar] Loaded from: file:/usr/share/ant/lib/sonar-ant-task-1.2.jar
[sonar:sonar] Sonar work directory: /var/lib/jenkins/jobs/buzzcartes/workspace/.sonar
[sonar:sonar] Sonar server: http://localhost:9000
BUILD FAILED
org.sonar.batch.bootstrapper.BootstrapException: http://localhost:9000/api/server /version
at org.sonar.batch.bootstrapper.Bootstrapper.getServerVersion(Bootstrapper.java:71)
at org.sonar.ant.SonarTask.checkSonarVersion(SonarTask.java:225)
at org.sonar.ant.SonarTask.execute(SonarTask.java:188)
at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:288)
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
at org.apache.tools.ant.Task.perform(Task.java:348)
at org.apache.tools.ant.Target.execute(Target.java:357)
at org.apache.tools.ant.Target.performTasks(Target.java:385)
at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1337)
at org.apache.tools.ant.Project.executeTarget(Project.java:1306)
at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41)
at org.apache.tools.ant.Project.executeTargets(Project.java:1189)
at org.apache.tools.ant.Main.runBuild(Main.java:758)
at org.apache.tools.ant.Main.startAnt(Main.java:217)
at org.apache.tools.ant.launch.Launcher.run(Launcher.java:257)
at org.apache.tools.ant.launch.Launcher.main(Launcher.java:104)
Caused by: java.io.FileNotFoundException: http://localhost:9000/api/server/version
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1610)
at java.net.URLConnection.getContent(URLConnection.java:748)
at org.sonar.batch.bootstrapper.Bootstrapper.remoteContent(Bootstrapper.java:123)
at org.sonar.batch.bootstrapper.Bootstrapper.getServerVersion(Bootstrapper.java:69)
... 18 more
I've updated the configuration in Jenkins to reflect the new location of http://localhost/sonar so I'm not sure where the http://localhost:9000/ is now coming from. I've looked in a variety of config files so far with no joy and Google isn't turning up any good answers so far. Any pointers would be most welcome.
Oh, my sonar task in build.xml looks like this:
<target name="sonar" depends="compile">
<!-- list of mandatory Sonar properties -->
<property name="sonar.sources" value="${basedir}/src" />
<!-- list of optional Sonar properties -->
<property name="sonar.projectName" value="buzzcartes" />
<property name="sonar.binaries" value="${basedir}/build" />
<property name="sonar.tests" value="${basedir}/test" />
<property name="sonar.libraries" value="${basedir}/lib" />
<sonar:sonar key="com.benjasoft:buzzcartes" version="0.1-SNAPSHOT" xmlns:sonar="antlib:org.sonar.ant" />
Thanks!
Try so set the sonar.host.url parameter
Maven
<sonar.host.url>http://wherever.sonar.com:9000</sonar.host.url>
Ant
<property name="sonar.host.url" value="http://wherever.sonar.com:9000" />
Strangely it is not documented here, but mentioned in the ant task guide.
I have the following Sonar Ant target defined:
<target name='sonar'>
<property name='sonar.sources' value='${src.dir}'/>
<property name='sonar.tests' value='${test.src.dir}'/>
<property name='sonar.binaries' value='build/classes'/>
<path id='jars'>
<fileset dir='${env.JAVA_HOME}/jre/lib' includes='*.jar'/>
<fileset dir='build/lib/test' includes='*.jar'/>
</path>
<pathconvert property='sonar.libraries' refid='jars' pathsep=','/>
<exec executable='p4' outputproperty='p4.P4CLIENT'>
<arg value='set'/>
<arg value='P4CLIENT'/>
</exec>
<propertyregex
property='p4client'
input='${p4.P4CLIENT}'
regexp='P4CLIENT=([^ ]+) *.*'
replace='\1'/>
<propertyregex
property='sonar.timestamp'
input='${build.time}'
regexp='_'
replace='T'/>
<sonar:sonar key='com.netflix:${module.name}' version='${p4client}#${sonar.timestamp}' xmlns:sonar='antlib:org.sonar.ant'/>
<property name='sonar.dynamicAnalysis' value='reuseReports'/>
<property name='sonar.emma.reportPath' value='${coverage.dir}'/>
</target>
When I run 'ant sonar' and bring up Sonar in my browser, I see info about the classes in the src directory, but nothing about the stuff in the test directory.
If I add ${test.src.dir} to sonar.sources and not set sonar.tests, I see some info about the test classes, but Sonar still reports 0 Test Successes.
How do I get it so I can drill down to each test method and their stats?
For anyone else that runs across this issue, I finally got Sonar to report on our Emma Code coverage. The first problem was that the Emma plugin did not come with the version of Sonar I was using (3.1.1). I had to download it and install it to the extensions/plugins directory of Sonar and restart it.
Then I had to set the following properties in my build.xml:
<property name="sonar.core.codeCoveragePlugin" value="emma" />
<property name="sonar.emma.reportPath" value="${coverage.dir}" />
After this, I atleast saw the following output after running the Sonar ant task:
[sonar:sonar] 13:41:49.705 WARN org.sonar.INFO - No coverage (*.ec) file found in /my/local/path
[sonar:sonar] 13:41:49.708 WARN org.sonar.INFO - No metadata (*.em) file found in /my/local/path
After some digging, I found that inside of the Sonar Emma plugin, it is hard-coded to look for a .ec (coverage) file and a .em (metadata) file. Unfortunately, my coverage file had a .emma extension as did my metadata file and I was unable to rename them as it would break other functionality. So I wrote the following Ant task to copy the files to match the naming standard that the Sonar Emma plugin expects.
<target name="createEmmaFilesWithSonarNamingStandard" depends="defineAntContribTasks">
<if>
<available file="${coverage.dir}/metadata.emma" />
<then>
<copyfile src="${coverage.dir}/metadata.emma" dest="${coverage.dir}/metadata.em" />
</then>
</if>
<if>
<available file="${coverage.dir}/coverage.emma" />
<then>
<copyfile src="${coverage.dir}/coverage.emma" dest="${coverage.dir}/coverage.ec" />
</then>
</if>
</target>
After running this again, I came across a new problem:
org.sonar.api.utils.SonarException: java.io.IOException: cannot read [/my/local/path/build/coverage/metadata.em]: created by another EMMA version [2.0.5312]
After some more digging, I found that the Sonar Emma 1.0.1 plugin was compiled against Emma 2.0.5312 and the Sonar Emma 1.1 and 1.2.x against Emma version 2.1.5320 as stated on the Sonar Emma plugin page.
I downloaded the 2.1.5320 version of Emma, replaced both emma.jar as well as emma_ant.jar in my Ant lib directory. After a clean re-compile and test, I was able to re-run the Sonar Ant task and have my code coverage reflected on Sonar.
The property 'sonar.surefire.reportsPath' needs to be defined before the definition of the sonar target.
The following definition gets the test info exported (although it's still not exporting coverage info):
<property name='sonar.surefire.reportsPath' value='${test.dir}'/>
<property name='sonar.dynamicAnalysis' value='reuseReports'/>
<property name='sonar.emma.reportPath' value='${coverage.report.dir}'/>
<target name='sonar'>
<property name='sonar.sources' value='${src.dir}'/>
<property name='sonar.tests' value='${test.src.dir}'/>
<property name='sonar.binaries' value='${build.dir}'/>
<path id='jars'>
<fileset dir='${env.JAVA_HOME}/jre/lib' includes='*.jar'/>
<fileset dir='${ivy.lib.dir}/test' includes='*.jar'/>
</path>
<pathconvert property='sonar.libraries' refid='jars' pathsep=','/>
<exec executable='p4' outputproperty='p4.P4CLIENT'>
<arg value='set'/>
<arg value='P4CLIENT'/>
</exec>
<propertyregex
property='p4client'
input='${p4.P4CLIENT}'
regexp='P4CLIENT=([^ ]+) *.*'
replace='\1'/>
<propertyregex
property='sonar.timestamp'
input='${build.time}'
regexp='_'
replace='T'/>
<sonar:sonar key='com.netflix:${module.name}' version='${p4client}#${sonar.timestamp}' xmlns:sonar='antlib:org.sonar.ant'/>
</target>