重复:蚂蚁是不是一种编程语言。实际上,在黑板上写下100次。
蚂蚁不是一种编程语言,所以不要这样想。它是一个构建依赖矩阵。
对于程序员来说,围绕这个想法很困难。他们想要告诉Ant每一步以及何时应该完成。他们想要循环,如果语句。他们会求助于使用build.sh
脚本来调用Ant中的各种目标,因为您无法轻松编程Ant。
在Ant中,您指定了离散任务,以及哪些任务依赖于其他任务,并让Ant处理执行任务的位置和时间。
我在说的是,你通常不会将任务分成子任务,然后尝试对它们调用<ant>
或<subant>
。
有离散任务,但让每个任务都知道他们依赖的其他任务。还要记住在Ant中没有真正的顺序。当你列出depends=
任务,也不能保证其顺序,他们将在执行。
标准的Ant风格(这意味着我的方式做到这一点(又名正确的方式),而不是我的方式同事这样做(aka The Wrong Way)),通常规定在属性文件的顶部定义任务,而不是在任何目标中定义任务。下面是我如何构建一个基本的轮廓我build.xml
:
<project name=...>
<!-- Build Properties File -->
<property name="build.properties.file"
value="${basedir}/build.properties"/>
<property file="${build.properties.file"/>
<!-- Base Java Properties -->
<property name="..." value="..."/>
<taskdef/>
<taskdef/>
<!-- Javac properties -->
<property name="javac..." value="..."/>
<task/>
<task/>
</project>
这就产生了一个有趣的层次。如果您有一个名为build.properties
的文件,它将覆盖build.xml
脚本中定义的属性。例如,您有:
<property name="copy.verbose" value="false"/>
<copy todir="${target}"
verbose="${copy.verbose}">
<fileset dir="${source}"/>
</copy>
您可以通过仅仅在build.properties
文件中设置copy.verbose = true
开启冗长的副本。
$ ant -Dbuild.properties.file="my.build.properties"
(是的,是的,我知道有一个为ant
一个-property
命令行参数)
我通常:而且,你可以仅仅通过指定在命令行上指定一个不同的构建属性文件将build.xml
中的各个值设置为假定的默认值,但任何人都可以通过创建build.properties
文件来更改它们。而且,由于所有的基本属性都在开头,所以很容易找到。
任务也在这个非目标空间中定义。这样,我可以很容易地找到定义,因为它们在每个build.xml
的相同位置,并且我知道我可以使用任务而不用担心任务定义目标是否已经命中。现在
,你的问题:
定义您的任务(并没有定义任务焦油,否则你会自己开车疯了)。然后,定义每个这些任务的依赖关系。开发人员可以选择他们想要击中的目标。例如:
<project>
<description>
yadda, yadda, yadda
</description>
<taskdef name="cobertura"/>
<target name="compile"
description="Compile the code"/>
<!-- Do you have to compile code before you run Cobertura?-->
<target name="coverage"
description="Calculate test coverage"
depends="compile">
<mkdir dir="${coverage.dir}"/>
<cobertura-instrument/>
</target>
<project>
如果你想编译代码,但不运行任何测试,你与compile
目标执行ant
。如果您想运行测试,则执行ant
,并使用coverage
目标。没有必要使用depends=
参数。
另请注意description=
参数和<description>
任务。这是因为如果你这样做:
$ ant -p
蚂蚁会显示哪些内容在<description>
任务,具有description
参数所有目标,而且描述。这样,开发人员就知道哪些目标用于哪些任务。
顺便说一句,我还建议做正确的方式(也就是我这样做),并在Maven lifecycle goals后命名您的目标。为什么?因为这是标准化目标名称的好方法。开发人员知道clean
将删除所有构建的工件,并且compile
将运行<javac>
任务,并且该test
将运行junit
测试。因此,您应该使用Cobertura plugin:cobertura
中的目标。
编辑
我的问题是:我把“覆盖”作为与“优化”和“调试”,即构建味道。这就是我的困难所在:对于Java,覆盖率在编译步骤中会产生额外的中间目标。
我看Corburta页面,并且有在<javac>
任务没有真正的改变(这是的一部分编译目标。
相反,你对已建成.class
文件运行Corburtura ,然后运行<junit>
任务。最大的变化是在你的<junit>
现在的任务,其中必须包括您Corburtura罐子引用,以及对你的仪表类。
我想像你可以有一个corburtura
目标或要什么都叫它。该目标运行仪器化的JUnit测试。这是您希望开发人员打的目标,并且应该包含运行仪器测试的说明。
当然,如果不先测试它们,您将无法运行测试的Junit测试。因此,您的corburtura
目标将取决于另一个instrument.tests
目标。这个目标是内部的。运行你的build.xml
的人通常不会在没有运行这些测试的情况下说“仪器测试”。因此,这个目标没有描述。
当然,instrument.tests
目标取决于其.class
文件到仪器,所以它必须就compile
目标的依赖在运行<javac>
任务:
<target name="instrument.classes"
depends="compile">
<coburtura-instrument/>
</target>
<target name="corburtura"
depends="instrument.classes"
description="Runs the JUnit tests instrumented with Corburtura">
<junit/>
</target>
唯一的问题是,你指定你的<junit>
目标两次:一次当仪表,一次正常测试。这可能是一个小问题。如果您更新了JUnit测试的运行方式,则必须在两个地方完成。
如果你想解决这个问题,你可以使用<macrodef>
来定义运行宏的JUnit测试。我使用了Corbertura页面上的内容来帮助提纲。完全没有经过测试,可能是语法错误:
<target name="instrument.tests"
depends="compile">
<corburtura-instrument/>
</target>
<target name="corburtura"
depends="instrument.tests"
description="Instrument and run the JUnit tests">
<run.junit.test fork.flag="true">
<systemproperty.addition>
<sysproperty key="net.sourceforge.corbertura.datafile"
file="${basedir}/cobertura.ser" />
</systemproperty.addition>
<pre.classpath>
<classpath location="${instrumented.dir}" />
</pre.classpath>
<post.classpath>
<classpath refid="cobertura_classpath" />
</post.classpath>
</run.junit.test>
</target>
<target name="test"
description="Runs the Junit tests without any instrumentation">
<run.junit.test/>
</target>
<macrodef name="run.junit.test">
<attribute name="fork.flag" default="false"/>
<element name="sysproperty.addition" optional="yes"/>
<element name="pre.classpath" optional="yes"/>
<element name="post.classpath" optional="yes"/>
<sequential>
<junit fork="@{fork.flag}" dir="${basedir}" failureProperty="test.failed">
<systemproperty.addtion/>
<pre.classpath/>
<classpath location="${classes.dir}" />
<post.classpath/>
<formatter type="xml" />
<test name="${testcase}" todir="${reports.xml.dir}" if="testcase" />
<batchtest todir="${reports.xml.dir}" unless="testcase">
<fileset dir="${src.dir}">
<include name="**/*Test.java" />
</fileset>
</batchtest>
</junit>
</sequential>
</macrodef>
(我使用ant 1.8.2) – xtofl