Из данной статьи Вы узнаете, как с помощью Apache Ant framework автоматически собирать Java проект, запускать тесты и многое другое.
Ant - это framework, с помощью которого можно избавиться от стандартного набора команд:
# javac ...
# java ...
которые приходится выполнять после изменений в коде. Для этого Вам нужно будет 1 раз настроить xml файл для проекта с соответствующими заданиями.
А далее запускать его либо вручную, либо через crontab либо через CI(Continuous Integretion) систему.
Смысл использования Ant в том, что в зависимости от этапа разработки(цикла) Вам необходимо выполнять различные виды сборок. К примеру, просто откомпилировать классы, сделать проверку с помощью unit-тестов, сгенерировать javadoc. Или выполнить все одновременно. Этим и занимается Ant - он позволяет настроить файл с заданиями и их комбинациями, которые можно вызывать последовательно.
Концепции Ant :
<project name="EnglishTesting" default="test"> <target name="test" description="Start test" > <echo>Performing of the tests....</echo> </target> </project>Таким образом мы создали задание "test" с одной командой "echo".
# ant -f build.xml test Buildfile: /home/masha/java/EnglishTesting/build.xml test: [echo] Performing of the tests.... BUILD SUCCESSFUL Total time: 1 secondНазывать задания можно как угодно, но лучше использовать следующие рекомендуемые наименования, которые для всех других разработчиков ясны и понятны:
Рассмотрим простое задание - скомпилируем наш проект в нужной директории.
Для этого создадим следующий build.xml файл:
<project name="EnglishTesting" default="compile"> <property name="src.java" location ="src"/> <property name="build.dir" location="build"/> <property name="build.classes.java" location="${build.dir}/class/java"/> <target name="make.dirs" description="Making of the auxillary dirs" > <mkdir dir="${build.dir}"/> <mkdir dir="${build.classes.java}"/> </target> <target name="compile" description="Compilation of the classes" depends="make.dirs"> <echo>Compilation ....</echo> <javac includeantruntime="false" destdir="${build.classes.java}"> <src path="${src.java}"/> </javac> </target> </project>Как Вы заметили мы задали набор property , где указали директории исходников, релизов. Атрибут location (value) - хранит значение переменной. Если Вы создаете переменную для хранения имени директории, то нужно указывать location, если нужно использовать переменную в качестве имени проекта, то используйте value.
# ant compile.java Buildfile: /home/masha/java/EnglishTesting/build.xml make.dirs: [mkdir] Created dir: /home/masha/java/EnglishTesting/build [mkdir] Created dir: /home/masha/java/EnglishTesting/build/class/java compile.java: [echo] Compiling classes... [javac] Compiling 4 source files to /home/masha/java/EnglishTesting/build/class/java BUILD SUCCESSFUL Total time: 1 second
Заметьте, если повторно запустить на выполнение эту же команду, то будет выдано следующее:
# ant compile.java Buildfile: /home/masha/java/EnglishTesting/build.xml make.dirs: compile.java: [echo] Compiling classes... BUILD SUCCESSFUL Total time: 0 secondsЭто значит, что если папки уже существуют, то они повторно не пересоздаются. А также если в коде не было изменений, то он также повторно не компилируется.
Для запуска тестов используется тег junit. Он имеет множество удобных настроек. Рассмотрим запуск простого теста на следующем примере. Для этого допишем в наш предыдущий build.xml файл новую задачу test:
<target name="compile.test" description="Compilation of the tests" depends="make.dirs, compile"> <echo>Compiling tests....</echo> <javac includeantruntime="false" destdir="${build.classes.test}"> <src path="${src.test}"/> <classpath> <pathelement location="${classpath.dir}/junit-4.5.jar"/> <pathelement location="${build.classes.java}"/> </classpath> </javac> </target> <target name="test" Start test EnglishTesting class" depends="compile.test"> <junit printsummary="yes" haltonerror="yes" haltonfailure="yes" fork="yes"> <formatter type="plain" usefile="false"/> <test name="testing.EnglishTestingTest"/> <classpath> <pathelement location="${classpath.dir}/junit-4.5.jar"/> <pathelement location="${build.classes.java}"/> <pathelement location="${build.classes.test}"/> </classpath> </junit> </target>Свойства ${build.classes.test}, ${classpath.dir} зададим заранее. Теперь запустим наш файл сборки:
# ant test Buildfile: /home/masha/java/EnglishTesting/build.xml make.dirs: [mkdir] Created dir: /home/masha/java/EnglishTesting/build [mkdir] Created dir: /home/masha/java/EnglishTesting/build/class/java [mkdir] Created dir: /home/masha/java/EnglishTesting/build/class/test [mkdir] Created dir: /home/masha/java/EnglishTesting/build/jar compile: [echo] Compiling classes... [javac] Compiling 4 source files to /home/masha/java/EnglishTesting/build/class/java compile.test: [echo] Compiling tests.... [javac] Compiling 2 source files to /home/masha/java/EnglishTesting/build/class/test test: [junit] Running testing.EnglishTestingTest [junit] Testsuite: testing.EnglishTestingTest [junit] Tests run: 10, Failures: 0, Errors: 0, Time elapsed: 0.061 sec [junit] Tests run: 10, Failures: 0, Errors: 0, Time elapsed: 0.061 sec [junit] [junit] Testcase: testCalcPercentNullQuestions took 0.007 sec [junit] Testcase: testCalcPercent took 0.001 sec [junit] Testcase: testCalcSkillIncrement took 0.001 sec [junit] Testcase: testCalcSkillIncrementErrors took 0 sec [junit] Testcase: testGetResultsExcelent took 0.001 sec [junit] Testcase: testGetResultsGood took 0 sec [junit] Testcase: testGetEnglishWord took 0 sec [junit] Testcase: testCheckAnswer took 0.001 sec [junit] Testcase: testCheckIncorrectAnswer took 0 sec [junit] Testcase: testGenerateAnswerForImproperWord took 0 sec BUILD SUCCESSFUL Total time: 3 secondsРассмотрим атрибуты junit более подробно.
<javac ...> <classpath> <pathelement location="${classpath.dir}/junit-4.5.jar"/> <pathelement location="${build.classes.java}"/> </classpath> </javac>2) либо
<project ... > <path id="project.class.path"> <pathelement location="${classpath.dir}/junit-4.5.jar" /> <pathelement location="${build.classes.java}"/> </path> <target ... > <javac ...> <classpath refid="project.class.path"/> </javac> </target> </project>Первый способ удобен, когда у Вас маленький проект и Вам нужно быстро набросать сборочный файл. Но лучше пользоваться вторым способом. Второй способ позволяет сэкономить, если придется указывать classpath и в других задачах java или javac.
Как говорилось выше результаты задания junit могут выводиться либо на консоль либо в файл. Для генерации html отчета необходимо создать задания следующего вида:
<target name="testsuite" description="Start TestSuite class" depends="compile.test"> <junit printsummary="yes" haltonerror="yes" haltonfailure="yes" fork="yes"> <formatter type="xml"/> <test name="suite.SuiteTests" todir="${html.report.dir}"/> <test name="testing.EnglishTestingTest" todir="${html.report.dir}"/> <classpath> <pathelement location="${build.classes.java}"/> <pathelement location="${build.classes.test}"/> </classpath> </junit> </target> <target name="report" description="" depends="testsuite"> <mkdir dir="${html.report.dir}/html"/> <junitreport todir="${html.report.dir}" > <fileset dir="${html.report.dir}"> <include name="TEST-*.xml"/> </fileset> <report todir="${html.report.dir}/html"/> </junitreport> </target>Первое, что мы делаем это сохраняем результаты проведенных тестов в XML. Далее мы используем элемент junitreport, он преобразует полученный xml в html в указанную в атрибуте todir директорию. Элемент fileset позволяет junitreport указать, какие именно xml файлы использовать для генерации html. Результаты в броузере можно посмотреть открыв index.html:
Каждый JAR файл содержит в себе файл MANIFEST.MF, который лежит в директории META-INF. MANIFEST.MF это текстовый файл, который содержит информацию о JAR архиве, например версию, конфигурацию, запускаемый класс. Сгенерируем JAR файл для нашего приложения с помощью следующего задания:
<target name="jar" description="Creating jar after tests" depends="compile, test"> <jar destfile="${build.jar}/EnglishTesting.jar" basedir="${build.classes.java}"> <manifest> <attribute name="Main-Class" value="userconsole.ViewTesting"/> <attribute name="Class-Path" value="${classpath.dir}/mysql-connector-java-5.1.14-bin.jar"/> <attribute name="Created-By" value="(с) Mariya Sokunova"/> </manifest> </jar> <target/>В нашем случае будем генерировать JAR файл только после корректного прохождения unit-тестирования. В MANIFEST.MF зададим атрибуты:
Если для проверки работоспособности Вашего приложения необходимо осуществляеть его запуск, то можно воспользоваться следующим заданием:
<target "run" description="Run application" depends="jar"> <echo>Running application . . . </echo> <java jar="${build.jar}/EnglishTesting.jar" fork="true"/> <target/>Заметьте, если Вы используете консольное приложение, то оно запускается в отдельном процессе, а не в том в котором запущен Ant. Поэтому вводить данные через консоль при этом не удастся.
Когда проект готов Вы возможно захотите сформировать для него документацию - javadoc. Если Вы используете соответствующие комментарии к классам, то сформировать документацию не сложно. Вам необходимо создать задание :
<target name="javadoc" description="Creating javadoc" depends="make.dirs"> <echo>Generation javadoc . . . </echo> <javadoc destdir="${javadoc.dir}" sourcepath="${src.java}" author="true" version="true" packagenames="*" windowtitle="EnglishTesting" use="true" > <bottom> <![CDATA[<b>Sokunova Mariya, 2011<b>]]> </bottom> </javadoc> </target>После запуска задания Вы получите готовую javadoc документацию :
Полный пример build.xml можно взять здесь. Более подробно об инструменте Apache Ant можно почитать здесь.