2011-04-16 3 views
2

S'il vous plaît excusez si la question est stupide, je suis seulement 2ème jour sur Ant et Java piratage ensemble une solution CI avec presque aucune connaissance de Ant ou Java. Par conséquent, je souhaite qu'une génération échoue si (mon) programme Java exécuté en tant qu'étape dans la génération décide que la génération doit échouer.Faire Java étape dans le script Ant échouer la construction

Je pensais juste jeter une exception non gérée dans le programme Java ou en utilisant System.exit() pour arrêter la JVM, mais ils semblent assez méchant.

Y a-t-il un bon moyen d'échouer la construction si une étape java le décide?

+2

"... ils semblent plutôt méchants ..." - veuillez décrire votre idée d'une manière "agréable" d'informer un utilisateur qu'un programme a échoué. – duffymo

+0

Quelque chose comme mon application java sortant avec un code de retour à la JVM, la JVM passant à Ant et Ant agissant sur elle pour échouer? – jontyc

+2

Retournez donc -1 lorsque vous appelez System.exit() et que vous continuez. – duffymo

Répondre

7

Pour la tâche <java>, il existe un attribut failonerror. Si vous définissez à yes (ou true), la construction échouera si le processus est retourné quoi que ce soit d'autre que 0.

Le problème est que pour le retour une valeur d'un appel java, cet appel doit System.exit(value). Pour ne pas tuer votre fourmi, vous devez également fournir fork=true pour exécuter dans une nouvelle JVM.

Ainsi, l'appel java pourrait ressembler à ceci:

<java jar="..." 
     fork="yes" 
     failonerror="yes"> 
</java> 

Bien sûr, vous pourriez aussi avoir votre programme Java API mettre en œuvre la tâche Ant et la charge/appeler comme une tâche de fourmi appropriée. Ensuite, il peut lui-même décider quoi faire (et sera plus configurable, aussi).

+0

Je pensais que c'est exactement ce que je recherchais, puis j'ai réalisé que j'utilise déjà 'failonerror' (je l'ai copié à partir d'un exemple et j'ai oublié qu'il était là). Je ne tenais pas trop à ce que la construction ne force pas la JVM à supprimer Ant, mais avec failonerror le gérant explicitement et la fourchette que vous mentionnez, je suis heureux. – jontyc

0

Ant devrait être simple. Il échoue une construction si une étape particulière ne réussit pas. Je pense que le comportement que vous voulez est déjà intégré. En ce qui concerne votre étape personnalisée, mon conseil serait de trouver un moyen de le faire en dehors de Ant pour l'instant pendant que vous faites fonctionner le reste du flux CI. Mieux vaut faire autant de progrès que de tomber dans un trou sur un détail.

Cela peut être utile si vous décrivez ce que fait votre programme. Il y a peut-être une meilleure façon d'accomplir ce dont vous avez besoin.

MISE À JOUR: Je ne pense pas que vous devriez aller dans cette direction. Les tests que vous exécutez avec CC doivent être des tests unitaires. Si vous devez empaqueter et déployer l'application à tester, j'appellerais ces tests d'intégration. Exécutez-les séparément dans le cadre de votre étape de contrôle qualité, pas la génération.

Vous faites la bonne chose avec Selenium; J'aime ta rigueur et ton effort. Mais je vous recommande d'exécuter uniquement les tests unitaires avec CC, de regrouper et de déployer l'application sur un serveur QA, puis d'exécuter vos tests Selenium sous forme de JUnits. Ils sont scriptés et rapides.

Je m'interroge également sur la sagesse de l'utilisation de Selenium pour vérifier les emplacements de widget dans l'interface utilisateur. Cela me semble fragile. mieux à gauche à un humain.

Voici une version générique Ant que je réutilise souvent. N'hésitez pas à l'utiliser comme référence. Continuez à vous dire "Cela devrait être simple." Si cela devient trop dur, vous le faites mal.

<?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> 
+0

Ce que je fais est d'avoir Ant checkout le code pour une application web et une application de test, compiler les deux, puis l'application de test (Java) conduire l'application web via Selenium 2, prendre un instantané d'écran et le comparer à un plan connu. Si cette étape de comparaison d'image échoue, alors je souhaite que la construction échoue. Tout fonctionne bien, je ne suis pas trop friand de l'une ou l'autre méthode que j'ai utilisée. – jontyc

+1

re: votre mise à jour: initialement l'intégration unique a été mise en CI car il n'y a qu'environ 30% de couverture des tests unitaires pour le moment et les ruptures dans le flux principal sont immédiatement corrigées pour accommoder les tests. Cependant, étant donné qu'un tel test d'intégration est entièrement automatisé et que la charge du serveur n'est pas un problème, je ne vois aucune raison de le retirer de CI après cette phase d'écriture de test unitaire. Il ne remplacera jamais les étapes ultérieures des tests bien sûr. – jontyc

1

Le manuel Ant montre une tâche intégrée nommée Fail que vous pouvez configurer avec des conditions spécifiques pour rendre la construction échouent.

<fail message="Files are missing."> 
    <condition> 
     <not> 
      <resourcecount count="2"> 
       <fileset id="fs" dir="." includes="one.txt,two.txt"/> 
      </resourcecount> 
     </not> 
    </condition> 
</fail> 

Vous pourriez vouloir regarder dans celui-là.

+0

Je connaissais , mais pas avec alors merci pour l'avance. En regardant dedans, la condition teste le code retour d'un donc il y a de la promesse là, merci. – jontyc

Questions connexes