Please excuse if the question is dumb, I'm only 2nd day on Ant and Java hacking together some CI solution with next to no knowledge of Ant or Java.
So I开发者_运维问答 wish a build to fail if (my) java program run as a step within the build decides that the build must fail.
I thought of just throwing an unhandled exception in the Java program or using System.exit() to shut down the JVM but they seem quite nasty.
Is there a nice way of ant failing the build if a java step decides it should?
For the <java>
task, there is an attribute failonerror
. If you set it to yes
(or true
), the build will fail if the process returned anything else than 0.
The problem is that for returning some value from a java call, this call must System.exit(value)
. For it to not kill your ant, you also need to provide fork=true
to run in a new JVM.
So, the java call could look like this:
<java jar="..."
fork="yes"
failonerror="yes">
</java>
Of course, you could also have your Java program implement the Ant Task API and load/call it as a proper ant task. Then it can itself decide what to do (and will be more configurable, too).
The Ant manual shows a built-in task named Fail which you can configure with specific conditions to make the build fail.
<fail message="Files are missing.">
<condition>
<not>
<resourcecount count="2">
<fileset id="fs" dir="." includes="one.txt,two.txt"/>
</resourcecount>
</not>
</condition>
</fail>
You might want to look into that one.
Ant ought to be straightforward. It does fail a build if a particular step does not succeed. I think the behavior you want is already built-in.
As for your custom step, my advice would be to find a way to do that outside of Ant for now while you get the rest of the CI flow working. Better to make that much progress rather than falling into a hole over one detail.
It might help if you describe what your program is doing. Perhaps there's a better way to accomplish what you need.
UPDATE: I don't think you should head down this path. The tests you run with CC should be unit tests. If you have to package and deploy the application to test, I'd call those integration tests. Run those separately as part of your QA step, not the build.
You're doing the right thing with Selenium; I like your rigor and effort. But I'd recommend running just the unit tests with CC, package and deploy the app to a QA server, then run your Selenium tests as JUnits. They're scripted and fast.
I also wonder about the wisdom of using Selenium to check for widget placements in the UI. That seems brittle to me; best left to a human.
Here's a generic Ant build that I re-use often. Feel free to use it as reference. Keep telling yourself "This ought to be simple." IF it gets too hard, you're doing it wrong.
<?xml version="1.0" encoding="UTF-8"?>
<project name="xslt-converter" basedir="." default="package">
<property name="version" value="1.6"/>
<property name="haltonfailure" value="no"/>
<property name="out" value="out"/>
<property name="production.src" value="src"/>
<property name="production.lib" value="lib"/>
<property name="production.resources" value="config"/>
<property name="production.classes" value="${out}/production/${ant.project.name}"/>
<property name="test.src" value="test"/>
<property name="test.lib" value="lib"/>
<property name="test.resources" value="config"/>
<property name="test.classes" value="${out}/test/${ant.project.name}"/>
<property name="exploded" value="out/exploded/${ant.project.name}"/>
<property name="exploded.classes" value="${exploded}/WEB-INF/classes"/>
<property name="exploded.lib" value="${exploded}/WEB-INF/lib"/>
<property name="reports.out" value="${out}/reports"/>
<property name="junit.out" value="${reports.out}/junit"/>
<property name="testng.out" value="${reports.out}/testng"/>
<path id="production.class.path">
<pathelement location="${production.classes}"/>
<pathelement location="${production.resources}"/>
<fileset dir="${production.lib}">
<include name="**/*.jar"/>
<exclude name="**/junit*.jar"/>
<exclude name="**/*test*.jar"/>
</fileset>
</path>
<path id="test.class.path">
<path refid="production.class.path"/>
<pathelement location="${test.classes}"/>
<pathelement location="${test.resources}"/>
<fileset dir="${test.lib}">
<include name="**/junit*.jar"/>
<include name="**/*test*.jar"/>
</fileset>
</path>
<path id="testng.class.path">
<fileset dir="${test.lib}">
<include name="**/testng*.jar"/>
</fileset>
</path>
<available file="${out}" property="outputExists"/>
<target name="clean" description="remove all generated artifacts" if="outputExists">
<delete dir="${out}" includeEmptyDirs="true"/>
<delete dir="${reports.out}" includeEmptyDirs="true"/>
</target>
<target name="create" description="create the output directories" unless="outputExists">
<mkdir dir="${production.classes}"/>
<mkdir dir="${test.classes}"/>
<mkdir dir="${reports.out}"/>
<mkdir dir="${junit.out}"/>
<mkdir dir="${testng.out}"/>
<mkdir dir="${exploded.classes}"/>
<mkdir dir="${exploded.lib}"/>
</target>
<target name="compile" description="compile all .java source files" depends="create">
<!-- Debug output
<property name="production.class.path" refid="production.class.path"/>
<echo message="${production.class.path}"/>
-->
<javac srcdir="src" destdir="${out}/production/${ant.project.name}" debug="on" source="${version}">
<classpath refid="production.class.path"/>
<include name="**/*.java"/>
<exclude name="**/*Test.java"/>
</javac>
<javac srcdir="${test.src}" destdir="${out}/test/${ant.project.name}" debug="on" source="${version}">
<classpath refid="test.class.path"/>
<include name="**/*Test.java"/>
</javac>
</target>
<target name="junit-test" description="run all junit tests" depends="compile">
<!-- Debug output
<property name="test.class.path" refid="test.class.path"/>
<echo message="${test.class.path}"/>
-->
<junit printsummary="yes" haltonfailure="${haltonfailure}">
<classpath refid="test.class.path"/>
<formatter type="xml"/>
<batchtest fork="yes" todir="${junit.out}">
<fileset dir="${test.src}">
<include name="**/*Test.java"/>
</fileset>
</batchtest>
</junit>
<junitreport todir="${junit.out}">
<fileset dir="${junit.out}">
<include name="TEST-*.xml"/>
</fileset>
<report todir="${junit.out}" format="frames"/>
</junitreport>
</target>
<taskdef resource="testngtasks" classpathref="testng.class.path"/>
<target name="testng-test" description="run all testng tests" depends="compile">
<!-- Debug output
<property name="test.class.path" refid="test.class.path"/>
<echo message="${test.class.path}"/>
-->
<testng classpathref="test.class.path" outputDir="${testng.out}" haltOnFailure="${haltonfailure}" verbose="2" parallel="methods" threadcount="50">
<classfileset dir="${out}/test/${ant.project.name}" includes="**/*.class"/>
</testng>
</target>
<target name="exploded" description="create exploded deployment" depends="testng-test">
<copy todir="${exploded.classes}">
<fileset dir="${production.classes}"/>
</copy>
<copy todir="${exploded.lib}">
<fileset dir="${production.lib}"/>
</copy>
</target>
<target name="package" description="create package file" depends="exploded">
<jar destfile="${out}/${ant.project.name}.jar" basedir="${production.classes}" includes="**/*.class"/>
</target>
</project>
精彩评论