java ant junit ivy

java - Clase no encontrada con Ant, Ivy y JUnit-error en build.xml?



(1)

Ejemplo

Proyecto contiene los siguientes archivos:

├── build.xml ├── ivy.xml └── src ├── main │   ├── java │   │   └── org │   │   └── demo │   │   └── App.java │   └── resources │   └── log4j.properties └── test └── java └── org └── demo └── AppTest.java

La compilación se ejecuta de la siguiente manera:

$ ant Buildfile: /home/mark/Files/Dev/ivy/demo/build.xml resolve: [ivy:resolve] :: Apache Ivy 2.3.0 - 20130110142753 :: http://ant.apache.org/ivy/ :: [ivy:resolve] :: loading settings :: url = jar:file:/home/mark/.ant/lib/ivy.jar!/org/apache/ivy/core/settings/ivysettings.xml [ivy:resolve] :: resolving dependencies :: com.myspotontheweb#demo;working@mark-Lemur-Ultra [ivy:resolve] confs: [compile, runtime, test] [ivy:resolve] found org.slf4j#slf4j-api;1.7.5 in public [ivy:resolve] found org.slf4j#slf4j-log4j12;1.7.5 in public [ivy:resolve] found log4j#log4j;1.2.17 in public [ivy:resolve] found junit#junit;4.11 in public [ivy:resolve] found org.hamcrest#hamcrest-core;1.3 in public [ivy:resolve] :: resolution report :: resolve 347ms :: artifacts dl 14ms --------------------------------------------------------------------- | | modules || artifacts | | conf | number| search|dwnlded|evicted|| number|dwnlded| --------------------------------------------------------------------- | compile | 1 | 0 | 0 | 0 || 1 | 0 | | runtime | 3 | 0 | 0 | 0 || 3 | 0 | | test | 5 | 0 | 0 | 0 || 5 | 0 | --------------------------------------------------------------------- [ivy:report] Processing /home/mark/.ivy2/cache/com.myspotontheweb-demo-compile.xml to /home/mark/Files/Dev/ivy/demo/build/ivy-reports/com.myspotontheweb-demo-compile.html [ivy:report] Processing /home/mark/.ivy2/cache/com.myspotontheweb-demo-runtime.xml to /home/mark/Files/Dev/ivy/demo/build/ivy-reports/com.myspotontheweb-demo-runtime.html [ivy:report] Processing /home/mark/.ivy2/cache/com.myspotontheweb-demo-test.xml to /home/mark/Files/Dev/ivy/demo/build/ivy-reports/com.myspotontheweb-demo-test.html resources: [copy] Copying 1 file to /home/mark/Files/Dev/ivy/demo/build/classes compile: [javac] Compiling 1 source file to /home/mark/Files/Dev/ivy/demo/build/classes compile-tests: [mkdir] Created dir: /home/mark/Files/Dev/ivy/demo/build/test-classes [javac] Compiling 1 source file to /home/mark/Files/Dev/ivy/demo/build/test-classes test: [mkdir] Created dir: /home/mark/Files/Dev/ivy/demo/build/test-reports [junit] Running org.demo.AppTest [junit] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0.085 sec build: [ivy:retrieve] :: retrieving :: com.myspotontheweb#demo [ivy:retrieve] confs: [runtime] [ivy:retrieve] 3 artifacts copied, 0 already retrieved (512kB/16ms) [jar] Building jar: /home/mark/Files/Dev/ivy/demo/build/dist/demo.jar BUILD SUCCESSFUL Total time: 4 seconds

ivy.xml

Una característica muy poderosa de la hiedra es la configuración . Esto le permite agrupar dependencias.

<ivy-module version="2.0"> <info organisation="com.myspotontheweb" module="demo"/> <configurations> <conf name="compile" description="Required to compile application"/> <conf name="runtime" description="Additional run-time dependencies" extends="compile"/> <conf name="test" description="Required for test only" extends="runtime"/> </configurations> <dependencies> <!-- compile dependencies --> <dependency org="org.slf4j" name="slf4j-api" rev="1.7.5" conf="compile->default"/> <!-- runtime dependencies --> <dependency org="org.slf4j" name="slf4j-log4j12" rev="1.7.5" conf="runtime->default"/> <!-- test dependencies --> <dependency org="junit" name="junit" rev="4.11" conf="test->default"/> </dependencies> </ivy-module>

Notas:

  • Las configuraciones usan la función "extends" para emular los alcances Maven "compilar", "runtime" y "test" Maven.
  • Tenga en cuenta el atributo especial "conf" en cada dependencia. Este es el mapeo de local a remoto. Para obtener más detalles sobre cómo los módulos Maven remotos son gestionados por hiedra, consulte: ¿Cómo se mapean los ámbitos Maven en hiedra?

build.xml

Las configuraciones de Ivy se pueden aprovechar mediante tareas como cachepath (para crear una ruta ANT) y recuperar (copiar archivos en su compilación). También recomiendo usar el objetivo del informe para que pueda ver qué jarras aparecen en cada configuración (Útil para administrar dependencias transitivas)

<project name="demo" default="build" xmlns:ivy="antlib:org.apache.ivy.ant"> <!-- ================ Build properties ================ --> <property name="src.dir" location="src/main/java"/> <property name="resources.dir" location="src/main/resources"/> <property name="test.src.dir" location="src/test/java"/> <property name="build.dir" location="build"/> <property name="classes.dir" location="${build.dir}/classes"/> <property name="test.classes.dir" location="${build.dir}/test-classes"/> <property name="ivy.reports.dir" location="${build.dir}/ivy-reports"/> <property name="test.reports.dir" location="${build.dir}/test-reports"/> <property name="dist.dir" location="${build.dir}/dist"/> <property name="jar.main.class" value="org.demo.App"/> <property name="jar.file" value="${dist.dir}/${ant.project.name}.jar"/> <available classname="org.apache.ivy.Main" property="ivy.installed"/> <!-- =========== Build setup =========== --> <target name="install-ivy" description="Install ivy" unless="ivy.installed"> <mkdir dir="${user.home}/.ant/lib"/> <get dest="${user.home}/.ant/lib/ivy.jar" src="http://search.maven.org/remotecontent?filepath=org/apache/ivy/ivy/2.3.0/ivy-2.3.0.jar"/> <fail message="Ivy has been installed. Run the build again"/> </target> <target name="resolve" depends="install-ivy" description="Use ivy to resolve classpaths"> <ivy:resolve/> <ivy:report todir=''${ivy.reports.dir}'' graph=''false'' xml=''false''/> <ivy:cachepath pathid="compile.path" conf="compile"/> <ivy:cachepath pathid="test.path" conf="test"/> </target> <!-- =============== Compile targets =============== --> <target name="resources" description="Copy resources into classpath"> <copy todir="${classes.dir}"> <fileset dir="${resources.dir}"/> </copy> </target> <target name="compile" depends="resolve,resources" description="Compile code"> <mkdir dir="${classes.dir}"/> <javac srcdir="${src.dir}" destdir="${classes.dir}" includeantruntime="false" debug="true" classpathref="compile.path"/> </target> <target name="compile-tests" depends="compile" description="Compile tests"> <mkdir dir="${test.classes.dir}"/> <javac srcdir="${test.src.dir}" destdir="${test.classes.dir}" includeantruntime="false" debug="true"> <classpath> <path refid="test.path"/> <pathelement path="${classes.dir}"/> </classpath> </javac> </target> <!-- ============ Test targets ============ --> <target name="test" depends="compile-tests" description="Run unit tests"> <mkdir dir="${test.reports.dir}"/> <junit printsummary="yes" haltonfailure="yes"> <classpath> <path refid="test.path"/> <pathelement path="${classes.dir}"/> <pathelement path="${test.classes.dir}"/> </classpath> <formatter type="xml"/> <batchtest fork="yes" todir="${test.reports.dir}"> <fileset dir="${test.src.dir}"> <include name="**/*Test*.java"/> <exclude name="**/AllTests.java"/> </fileset> </batchtest> </junit> </target> <!-- ===================== Build and run targets ===================== --> <target name="build" depends="test" description="Create executable jar archive"> <ivy:retrieve pattern="${dist.dir}/lib/[artifact]-[revision](-[classifier]).[ext]" conf="runtime"/> <manifestclasspath property="jar.classpath" jarfile="${jar.file}"> <classpath> <fileset dir="${dist.dir}/lib" includes="*.jar"/> </classpath> </manifestclasspath> <jar destfile="${jar.file}" basedir="${classes.dir}"> <manifest> <attribute name="Main-Class" value="${jar.main.class}" /> <attribute name="Class-Path" value="${jar.classpath}" /> </manifest> </jar> </target> <target name="run" depends="build" description="Run code"> <java jar="${jar.file}" fork="true"/> </target> <!-- ============= Clean targets ============= --> <target name="clean" description="Cleanup build files"> <delete dir="${build.dir}"/> </target> <target name="clean-all" depends="clean" description="Additionally purge ivy cache"> <ivy:cleancache/> </target> </project>

Nota:

  • El objetivo condicional "install-ivy" instalará ivy automáticamente. Simplemente vuelva a ejecutar la compilación, solo debe hacerse una vez.

App.java

Hola ejemplo de registro mundial.

package org.demo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Hello world! * */ public class App { static final Logger log = LoggerFactory.getLogger(App.class); public static void main( String[] args ) { App a = new App(); a.speak("hello world"); } public void speak(String message) { log.info(message); } }

AppTest.java

Este es un viejo ejemplo de mis archivos. No usar las aserciones de Junit.

ackage org.demo; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; /** * Unit test for simple App. */ public class AppTest extends TestCase { /** * Create the test case * * @param testName name of the test case */ public AppTest( String testName ) { super( testName ); } /** * @return the suite of tests being tested */ public static Test suite() { return new TestSuite( AppTest.class ); } /** * Rigourous Test :-) */ public void testApp() { assertTrue( true ); } }

log4j.properties

# Set root logger level to DEBUG and its only appender to A1. log4j.rootLogger=DEBUG, A1 # A1 is set to be a ConsoleAppender. log4j.appender.A1=org.apache.log4j.ConsoleAppender # A1 uses PatternLayout. log4j.appender.A1.layout=org.apache.log4j.PatternLayout log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n

Estoy tratando de obtener un proyecto de prueba simple (?) Que trabaje con Ant, Ivy y JUnit. La idea básica es que Ivy descargará junit.jar y luego Ant lo usará.

Tenga en cuenta que el junit jar está en classpath porque de lo contrario (sin el elemento classpath en la tarea junit) veo "El <classpath> for <junit> debe incluir junit.jar si no está en el propio classpath de Ant". Además, la clase dada a continuación (junit.framework.TestListener) está en junit-4.8.2.jar.

Sin embargo, cuando pruebo la ant test en lo siguiente veo:

test: BUILD FAILED /home/andrew/project/guice/hg/build.xml:33: java.lang.NoClassDefFoundError: junit/framework/TestListener at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:791) ... 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.ClassNotFoundException: junit.framework.TestListener at java.net.URLClassLoader$1.run(URLClassLoader.java:366) at java.net.URLClassLoader$1.run(URLClassLoader.java:355) ...

¿Entonces supongo que algo está mal con mi build.xml? ¿Qué?

Aquí está el build.xml:

<project xmlns:ivy="antlib:org.apache.ivy.ant" name="java-example" default="dist" basedir="."> <description> simple example build file </description> <property name="src" location="src"/> <property name="build" location="build"/> <property name="dist" location="dist"/> <property name="lib" location="lib"/> <path id="lib.path"> <fileset dir="${lib}"/> </path> <target name="init"> <tstamp/> <mkdir dir="${build}"/> </target> <target name="compile" depends="init,resolve" description="compile the source"> <javac srcdir="${src}" destdir="${build}" classpathref="lib.path" includeantruntime="false"> <compilerarg value="-Xlint"/> </javac> </target> <target name="test" depends="compile" description="run the tests"> <junit> <classpath refid="lib.path"/> <batchtest> <fileset dir="${build}"> <include name="**/*Test.class"/> </fileset> </batchtest> </junit> </target> <target name="dist" depends="compile" description="generate the distribution"> <mkdir dir="${dist}/lib"/> <jar jarfile="${dist}/lib/example-${DSTAMP}.jar" basedir="${build}"/> </target> <target name="clean" description="clean up"> <delete dir="${build}"/> <delete dir="${dist}"/> </target> <target name="resolve" description="download required dependencies"> <ivy:retrieve/> </target> </project>

y la estructura de directorio existente después de la compilación:

. ├── build │   └── com │   └── isti │   └── example │   ├── AppendToList.class │   ├── DumpToStdout.class │   ├── LimitedCounter.class │   ├── MessageSink.class │   ├── MessageSource.class │   └── SinkToSourceTest.class ├── build.xml ├── dist │   └── lib │   └── example-20130412.jar ├── ivy.xml ├── lib │   ├── junit-4.8.2.jar │   ├── junit-4.8.2-javadoc.jar │   └── junit-4.8.2-sources.jar ├── README.md └── src ├── main │   └── java │   └── com │   └── isti │   └── example │   ├── AppendToList.java │   ├── DumpToStdout.java │   ├── LimitedCounter.java │   ├── MessageSink.java │   └── MessageSource.java └── test └── java └── com └── isti └── example └── SinkToSourceTest.java

Actualización Incidentalmente, la ant -lib lib test (explícitamente dando el directorio lib) funciona. Y hay muchas descripciones confusas del manejo de esto en resultados de búsqueda web aleatorios, pero mi impresión es que el enfoque anterior es consistente con los últimos documentos (estoy usando hormiga 1.9) - ver el punto 5. Así que estoy pensando que esto puede ser un error ; error .