Currently I use an IDE for all my builds and unit tests. Now I have a need to use ant. I found a few simple ant build.xml scripts but they didn't support a separate Junit test/ dir. My projects are structured as follows:
src/
com/foo/
com/bar/
test/ -- Mirror of src/, with all *Test.java files.
com/foo/
com/bar/
lib/ -- All Java libs, including junit 4.
How can a construct a small ant script that builds my src/ and test/ Java classes then runs all my JUnit tests?
I define <path> elements for each target.
This is an excerpt from my build file, you'll have to adapt some paths and properties, but you can get the idea:
<path id="src.path">
<pathelement path="src/"/>
</path>
<path id="compile.path">
<path refid="src.path"/>
<fileset dir="lib/">
<include name="**/*.jar"/>
</fileset>
</path>
<path id="unit.test.path">
<path refid="compile.path"/>
<pathelement path="test/"/>
</path>
<target name="compile">
<javac destdir="bin">
<src path="src"/>
<classpath refid="compile.path"/>
</javac>
</target>
<target name="compileUnitTests" depends="compile">
<javac srcdir="test/" destdir="bin">
<classpath refid="unit.test.path"/>
</javac>
</target>
<target name="runUnitTests" depends="compileUnitTests">
<junit printsummary="yes" haltonfailure="no">
<jvmarg value="-Dfile.encoding=UTF-8"/>
<classpath refid="unit.test.path"/>
<formatter type="xml"/>
<batchtest fork="yes" todir="${this.report}">
<fileset dir="test">
<include name="${test.pattern}"/>
<exclude name="**/AllTests.class"/>
<exclude name="**/*$*.class"/>
</fileset>
</batchtest>
</junit>
</target>
And if you need to refine this to your needs, as cotton.m says, go read the ant task docs. Using ant with your specific directory structure does require some knowledge of the tool, don't expect you'll easily find ready-made examples that just work with your exact requirements.
I don't understand the question. Are you asking how to set the default target? Select which target to run when executing or do you just not know how to write build.xml files? It's not that hard really. See http://ant.apache.org/manual/tutorial-HelloWorldWithAnt.html and http://ant.apache.org/manual/
Related
I am new to Ant and getting java.lang.ClassNotFoundException. when running my Junit from eclipse / Ant build.xml, However, when running my unit test from eclipse by itself my test passes with no issue. There should be something wrong with my classpath which i cannot figure out.
My envrmnts are:
Java_home: C:/Program Files/Java/jdk1.7.0_25
Ant_home: C:/Users/Armen/javaFolder/apache-ant-1.9.2/bin
JUnit_home: C:/Users/Armen/javaFolder/apache-ant-1.9.2/bin/junit-4.10.jar
My Build.xml
<property name="junitLocation">C:/Users/Armen/javaFolder/apache-ant-1.9.2/bin/junit-4.10.jar</property>
<property name="antLocation2">C:/Users/Armen/JavaFolder/apache-ant-1.9.2.jar</property>
<property name="testCode">C:/Users/Armen/workspace/MockingObjects/test/demo</property>
<property name="srcCode">C:/Users/Armen/workspace/MockingObjects/src/demo</property>
<target name="compile" depends="clean">
<javac includeantruntime="false" srcdir="./src" destdir="./staging" ></javac>
</target>
<target name="run" depends="compile, unitTest">
<java classname="demo.AccountService"><classpath path="./staging"></classpath></java>
</target>
<target name="unitTest" depends="compile">
<junit printsummary="true" showoutput="true" haltonfailure="false" fork="yes">
<formatter type="plain" usefile="true"/>
<test name="demo.TestAccountService" outfile="./result" ></test>
<classpath>
<pathelement location="${junitLocation}"/>
<pathelement location="${antLocation}"/>
<pathelement location="${testCode}" />
<pathelement location="${srcCode}"/>
</classpath>
</junit>
</target>
<target name="clean">
<delete dir="staging"></delete>
<mkdir dir="./staging"/>
</target>
enter image description here
You don't have any step in your build script to compile the unit tests, and when you tell JUnit to run, you also don't include the compiled classes in the classpath - only the source files.
There are therefore 2 things you need to do:
Add an additional build step similar to the following
<target name="test-compile" depends="compile">
<javac includeantruntime="false" srcdir="./test" destdir="./test-classes" />
</target>
then change your current unitTest target to depend on test-compile rather than compile.
Tell JUnit where your classes are, not your source code. Change your testCode and srcCode properties to
<property name="testCode">C:/Users/Armen/workspace/MockingObjects/test-classes</property>
<property name="srcCode">C:/Users/Armen/workspace/MockingObjects/staging</property>
Note From your compile and run steps, it isn't clear if your code is properly structured in Java Packages or, if it is in packages, that you understand how these work. I've made the assumption that your code is in a package of demo and therefore stripped that part of the path out of your compiled class locations.
The following is a simplified version of my ant script (it's got the project element etc).
I'm new to ant and unable to figure out why 'compileTests' doesn't compile, whereas 'compileFoo' does.
The error I get is 'package does not exist' as the class in the compileTests project can't find the compiled classes in the compileFoo project, even though they've compiled fine, i can see them on the file system and the path to them is listed in the classpath (i assume this is necessary?)
Clearly there is something basic I don't understand. Can someone please help by explaining?
<path id="build_classpath">
<fileset dir="${other_required_jars}" includes="**/*.jar" />
<fileset dir="${foo_build_location}" includes="**/*.class" />
</path>
<target name="compileFoo" description="compile">
<javac srcdir="${foo_source_directory}\test-src" includeantruntime="false" destdir="${foo_build_location}" includes="**/*.java" excludes="" debug="on" optimize="off" deprecation="on" verbose="on">
<classpath refid="build_classpath" />
</javac>
</target>
<target name="compileTests" description="compile">
<javac srcdir="${test_source_directory}\test-src" includeantruntime="false" destdir="${test_build_location}" includes="**/*.java" excludes="" debug="on" optimize="off" deprecation="on" verbose="on">
<classpath refid="build_classpath" />
</javac>
</target>
Your classpath is wrong. A classpath doesn't contain a set of .class files. It cntains a set of jar or directories, each containing the root of a package tree. So the classpath should simply contain one element : ${foo_build_location}:
<path id="build_classpath">
<fileset dir="${other_required_jars}" includes="**/*.jar" />
<pathelement location="${foo_build_location}"/>
</path>
We are using JiBX. The important thing to know is that JiBX modifies the already compiled class files.
We do our compile:
<javac destdir="${main.destdir}">
<src path="${main.srcdir}"/>
<classpath refid="main.classpath"/>
</javac>
Then, we call JiBX:
<jibx load="true"
binding="{$binding.file}">
<classpath refid="main.classpath"/>
<classpath refid="main.destdir.classpath"/>
</jibx>
This uses an XML file that updates the classfiles compiled by <javac> above. The problem is how do I know that the files have been compiled, but not processed by JiBX? I'd like to put some logic in my program, so that files are not updated twice by JiBX. Besides, it's bad form to duplicate work that already been done.
After the jibx build step, generate a marker file, e.g.
<touch file="${target.dir}/jibx.marker" />
Only perform the jibx build step if that marker file is older than the .class files (indicating that the javac ran more recently than the last jibx).
For that bit of logic, you can use the traditional ant way:
<uptodate property="jibx.uptodate" targetfile="${target.dir}/jibx.marker">
<srcfiles dir="${main.destdir}" includes="...../*.class" />
</uptodate>
And then use the property with an unless clause when invoking the jixb target.
Or, you can use Antcontrib's outofdate alternative:
<outofdate>
<sourcefiles>
<fileset dir="${main.destdir}" includes="...../*.class" />
</sourcefiles>
<targetfiles>
<fileset dir="${target.dir}" includes="jibx.marker"/>
</targetfiles>
<sequential>
<jibx load="true"
binding="{$binding.file}">
<classpath refid="main.classpath"/>
<classpath refid="main.destdir.classpath"/>
</jibx>
</sequential>
</outofdate>
I'm giving this to Patrice M. because his suggestion put me on the right track. However, it didn't quite work out as he stated. (Sorry, if I got he pronoun wrong, but Patrice can be both a male or female name.)
What I had to do was create two watch files: One for the Java compile, and one for the JiBX changes.
<!-- Check if Javac is out of date. If so, create javac watcher -->
<outofdate verbose="true">
<sourcefiles>
<fileset dir="${main.srcdir}">
<include name="*.java"/>
</fileset>
</sourcefiles>
<mapper type="regexp"
from="${main.srcdir}/(.*)\.java"
to="${main.destdir}/(\1).class"/>
<sequential>
<echo message="Java compiled"/>
<echo message="Java compiled"
file="${target.dir}/${javac.monitor.file}"/>
</sequential>
</outofdate>
<javac destdir="${main.destdir}"
debug="${javac.debug}">
<src path="${main.srcdir}"/>
<classpath refid="main.classpath"/>
</javac>
<!-- Compare javac and jibx monitoring file -->
<!-- If out of date, rerun jibx -->
<outofdate>
<sourcefiles>
<fileset dir="${target.dir}">
<include name="${javac.monitor.file}"/>
</fileset>
</sourcefiles>
<targetfiles>
<fileset dir="${target.dir}">
<include name="${jibx.monitor.file}"/>
</fileset>
</targetfiles>
<sequential>
<jibx load="true"
binding="${target.dir}/binding-gg.xml">
<classpath refid="main.classpath"/>
<classpath refid="main.destdir.classpath"/>
</jibx>
<!-- Create JiBX monitoring file -->
<echo message="Compiled and JiBX"
file="${target.dir}/${jibx.monitor.file}"/>
</sequential>
</outofdate>
I create the javac monitoring file if the source is out of date with the classes because that's when I compile. I have to create the JiBX outofdate monitoring file only when I run JiBX and that's inside the <outofdate> for JiBX.
I guess I could also put a source on the XML JiBX files too just to be sure.
I am not using an automated build tool. Just Checkstyle 5.5 and ANT 1.8.
I am trying to have Checkstyle run in my ANT script. The ANT script executes without error, but doesn't seem to call Checkstyle. I get no output except ANT reports BUILD SUCCESSFUL.
Here is my ant script:
<project name="ccu" xmlns:cs="antlib:com.puppycrawl.tools.checkstyle">
<target name="checkstyle" description="Generates a report of code convention violations.">
<cs:checkstyle config="custom_check.xml">
<fileset dir="src" casesensitive="yes">
<include name="**/*.java"/>
</fileset>
<!--
<fileset dir="src" includes="**\*.java"/>
-->
</cs:checkstyle>
</target>
</project>
what am i missing?
It was a classpath problem. For some reason I needed to direct the ANT classpath to the class files not the jar.
My final script looks like this:
<project name="ccu" xmlns:cs="antlib:com.puppycrawl.tools.checkstyle">
<taskdef resource="checkstyletask.properties">
<classpath>
<pathelement location="C:\myClasses\bin"/>
<pathelement location="C:\checkstyle-5.5\checkstyle-5.5-all.jar"/>
</classpath>
</taskdef>
<checkstyle config="custom_check.xml">
<fileset dir="src" includes="**/*.java"/>
</checkstyle>
</project>
I am trying some code-coverage analysis for first time and I was working on getting cobertura using ANT. My questions might be silly, but thought of asking here. I have the following in my ANT scripts. While reading over through cobertura the next step was instrumentation. What is code coverage instrumentation?
<target name="cobertura" depends="checkstyle">
<property name="cobertura.dir" location="C:\\Softwares- packages\\Corbetura\\cobertura-1.9.4.1" />
<path id ="cobertura.classpath">
<fileset dir="${cobertura.dir}">
<include name="cobertura.jar"/>
<include name="lib/**/*.jar"/>
</fileset>
</path>
<taskdef resource="tasks.properties" classpathref="cobertura.classpath"/>
</target>
cobertura modifies your class files so that it can compute the coverage. I typically 'instrument' a copy of the jar files that I use for executing tests and use a copy that hasn't been instrument as my build artifact.
Here is the build file I used when I first set up cobertura via ant:
The cobertura-instrument target instruments my code and writes the instrumented classes to a separate directory like you said.
The junit target compiles the test, then instruments the tests, then runs the tests, then produces the report. These steps are all done by declaring dependent targets to the junit one.
<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" />
<!-- Delete an existing coburtura datafile -->
<delete file="${cobertura.datafile}"/>
<antcall target="cobertura.clean"/>
<!-- Instrument the code with cobertura to test for coverage -->
<cobertura-instrument todir="${cobertura.instrumented.classes}" datafile="${cobertura.datafile}">
<fileset dir="${build.dir}/classes/">
<include name="**/*.class"/>
</fileset>
</cobertura-instrument>
<fileset dir="${src.dir}">
<include name="**/*.java" />
</fileset>
<fileset dir="${tests.src.dir}">
<include name="**/*.java" />
</fileset>
I believe you're looking for the "cobertura-instrument" task. See here