I have a JAVA ANT project and I am trying to integrate PMD scripts with it so that I can check for all errors and warnings in my project.
Below is snippet of ANT script which I have added in my build.xml:
<property name="pmd.dir" value="buildconfig/build/pmd/" />
<path id="pmd.lib" >
<fileset dir="${pmd.dir}">
<include name="*.jar"/>
<exclude name="/rulesets" />
</fileset>
</path>
<target name="pmd" depends="init">
<echo message="PMD Starting-----" />
<taskdef name="pmd" classname="net.sourceforge.pmd.ant.PMDTask" classpathref="pmd.lib"/>
<pmd shortFilenames="true">
<ruleset>unusedcode</ruleset>
<formatter type="text" toFile="${pmd.dir}/pmd-ant-results.txt"/>
<fileset dir="modules/app/">
<include name="**/*.java"/>
</fileset>
</pmd>
</target>
ANT build is working fine with PMD giving proper error reports but I need to abort the build as failure when PMD encounters any errors in code.
I tried adding failOnRuleViolation="yes" but that did not stop build.
Is there anything else I need to add in script?
Try failOnRuleViolation="true" instead of failOnRuleViolation="yes"...
<pmd shortFilenames="true" failOnRuleViolation="true">
...
Some Ant tasks treat true and yes as equivalent, but many tasks don't know how to handle yes at all. It is possible that <pmd> is one of those tasks that doesn't handle yes.
As a rule of thumb, avoid this gotcha in the future by always using true and false instead of yes and no.
Related
Below is the code for setting class path in ant.
<path id="build.classpath">
<fileset dir="${lib.dir}">
<include name="**/*.jar" />
</fileset>
</path>
<target name="compile" depends="clean">
<javac srcdir="${src.dir}" destdir="${build.dir}" classpathref="build.classpath" />
</target>
Why do we need to set classpath in ant ?
Think of ant as a framework to run your build tasks - compiling the code, running the (unit) tests, etc. In order to properly compile and execute your (test) code, java will need access to the third party libraries you may be using (e.g., JUnit for running unit tests). The classpath tells java where these JARs are located, so it can use them.
I have an Ant Build file. I added jacoco coverage task to get the coverage of my junit testcases. It says process fork failed.
<jacoco:coverage output="file" destfile="${result.exec.file}">
<!-- forkmode="perTest" printsummary="on" maxmemory="3072m" failureProperty="test.failure" haltonerror="false" includeAntRuntime="true"-->
<junit printsummary="on" fork="true">
<classpath refid="test.run.path" />
<syspropertyset>
<propertyref builtin="commandline" />
</syspropertyset>
<!-- usefile="true" -->
<formatter type="xml" usefile="true" />
<!-- failureproperty="test.failure" haltonerror="false" -->
<batchtest todir="reports/junit-xml" fork="yes">
<fileset dir="src/test/java">
<include name="**/AllTest.java" />
</fileset>
</batchtest>
</junit>
</jacoco:coverage>
<junitreport todir="${reports.dir}/junit-xml">
<fileset dir="${reports.dir}/junit-xml">
<include name="TEST-*.xml" />
</fileset>
<report format="frames" todir="${reports.dir}/junit-html" />
</junitreport>
Have you tried this without jacoco? I ask because I'm having the same problem with fork failure and I'm not using jacoco. I also have another project's ant script doing the same thing and it works fine. Yet somehow the project and ant script I'm currently working on fails the fork. In both cases I have to have fork set to "yes" because I'm specifying an alternate jvm for the junit block.
Maybe the classpath length issue is worth exploring. I know that in my case the ant script that's failing the fork has a longer class path than the one that's working. I had another project with a longer classpath that was also failing to fork but I didn't really need to fork so I just set it to "no".
I'm in the process of setting up a project which uses TeamCity to build the project and run the unit tests.
The first has been done successfully and the project builds. However I can't figure out how to set up TeamCity or my build.xml such that I can view the success or failure of each individual test. Although I'm quite sure I'm attacking this from the wrong angle.
Below is my build.xml:
<project>
<property name="test" location="tests"/>
<target name="test">
<junit printsummary="yes" fork="yes" haltonfailure="yes">
<formatter type="plain"/>
<batchtest fork="true">
<fileset dir="${test}">
<include name="**/*Test*.java"/>
</fileset>
</batchtest>
</junit>
</target>
</project>
This post on stack overflow answered my main problem. So I'll close this.
Simply generating the ANT build file from within eclipse did the trick.
Now for the reporting...
I have a java project that has just been imported into TFS and I've been trying to get TFS to output the results of the unit tests.
At the end of the TFSBuild.proj file I have the following:
<ItemGroup>
<!-- Ant Call Configuration.
The build file called should be included in the workspace of the build definition.
-->
<AntBuildFile Include="$/PROJECT_NAME/Main/tfsbuild.xml">
<Targets>build,test</Targets>
<Properties>BinariesRoot=$(BinariesRoot);BuildDefinitionName=$(BuildDefinitionName);BuildDefinitionUri=$(BuildDefinitionUri);BuildDirectory=$(BuildDirectory);BuildNumber=$(BuildNumber);DropLocation=$(DropLocation);LogLocation=$(LogLocation);SourceGetVersion=$(SourceGetVersion);TestResultsRoot=$(TestResultsRoot);TeamProject=$(TeamProject);WorkspaceName=$(WorkspaceName);WorkspaceOwner=$(WorkspaceOwner)</Properties>
<Lib></Lib>
</AntBuildFile>
<!-- JUnit XML Results files should be created using the XML formatter
and be located in the following path
-->
<JUnitLogFiles Include="$(BinariesRoot)\**\TEST-*.xml" />
</ItemGroup>
This kicks off the build and tells TFS where to find the junit test results.
The issue is, TFS is not finding the unit test results even though I can see through the logs that the tests were run.
I almost gave up on this, and changed my ant file to produce a junit report and store it with the build artifacts. I changed my ant task to be:
<target name="test" depends="compile-tests">
<echo>Running unit tests, output should be in ${junit.output}</echo>
<junit printsummary="yes">
<classpath>
<pathelement path="${compile.classpath}" />
<pathelement path="${lib.dir}/junit-4.0.jar" />
<pathelement path="${build}" />
<pathelement path="${dist-classes}" />
</classpath>
<formatter type="xml" />
<batchtest fork="yes" todir="${junit.output}">
<fileset dir="${src.test}">
<include name="**/*Test.java" />
</fileset>
</batchtest>
</junit>
<mkdir dir="${DropLocation}/${BuildNumber}/test_results" />
<junitreport todir="${junit.output}">
<fileset dir="${junit.output}">
<include name="TEST-*.xml" />
</fileset>
<report todir="${DropLocation}/${BuildNumber}/test_results" />
</junitreport>
</target>
But after checking the output from the next build, I realised that the JUnit output was saved as TESTS-TestSuites.xml, not TEST-*.xml. I changed my TFSBuild.proj file accordingly, and now have the build results appearing in TFS.
Somehow the junitreport task still picks up the output though.
I tried to get Cobertura running inside my ant script, but I'm stuck right at the beginning. When I try to insert the cobertura taskdef I'm missing the Log4J libraries.
Ant properties & classpath
<property name="cobertura.dir" location="/full/path/to/cobertura-1.9.3" />
<path id="cobertura.classpath">
<fileset dir="${cobertura.dir}">
<include name="cobertura.jar" />
<include name="lib/**/*.jar" />
</fileset>
</path>
<taskdef classpathref="cobertura.classpath" resource="tasks.properties" />
My ant target
<!-- =================================
target: cobertura
================================= -->
<target name="cobertura" depends="clean, init" description="Generates cobertura coverage reports">
<cobertura-instrument todir="${dir.build.instrumented}">
<fileset dir="${dir.build}">
<include name="**/*.class" />
</fileset>
</cobertura-instrument>
</target>
I think I did everything like it is described in the Cobertura documentation but I get this
Ant build error
BUILD FAILED
build.xml:95: java.lang.NoClassDefFoundError: org/apache/log4j/Logger
Inside the ${cobertura.dir} there is the lib directory with all files. I unzipped it from the cobertura distribution ZIP directly into that directory.
Am I missing a step? Something wrong with my configuration so far?
I also encountered this problem today and solved it by specifying the location of all the required libraries as part of the class path provided to my taskDef task.
<path id="cobertura.class.path">
<pathelement location="${common.dir}/../tools/cobertura/cobertura.jar" />
<pathelement location="${common.dir}/../tools/cobertura/lib/asm-3.0.jar" />
<pathelement location="${common.dir}/../tools/cobertura/lib/asm-tree-3.0.jar" />
<pathelement location="${common.dir}/../tools/cobertura/lib/log4j-1.2.9.jar" />
<pathelement location="${common.dir}/../tools/cobertura/lib/jakarta-oro-2.0.8.jar" />
</path>
<taskdef classpathref="cobertura.class.path" resource="tasks.properties" />
Go to your ant/lib dir and make sure there is NO file cobertura.jar there. If it's there - remove it and try again.
Change this
<include name="lib/**/*.jar" />
to
<include name="*.jar" />
Hope this helps!
I just upgraded to the latest cobertura and mine works fine. Is it possible that something else is on the CLASSPATH with a different version of log4j so it is picking up wrong one?
Make sure that classpath used in taskdef and cobertura-instrument are the same. This helped me with the same issue.
I too faced this problem, I just added all jars given with cobertura in the classpath to resolve this issue