Coding style ant条件目标和';递归';
我对ant还比较陌生,我看过Bob叔叔的《直到你放弃》一集 因此,我尝试将ant目标定义得尽可能小,这样您就可以准确地看到目标的本质,不再需要更多。有关更多详细信息,请参考子目标 这种风格是好是坏是另一种争论(或者可能是一场火焰战) 因此,我创建了一个构建脚本,在伪代码中,该脚本如下所示:Coding style ant条件目标和';递归';,coding-style,ant,if-statement,dependencies,Coding Style,Ant,If Statement,Dependencies,我对ant还比较陌生,我看过Bob叔叔的《直到你放弃》一集 因此,我尝试将ant目标定义得尽可能小,这样您就可以准确地看到目标的本质,不再需要更多。有关更多详细信息,请参考子目标 这种风格是好是坏是另一种争论(或者可能是一场火焰战) 因此,我创建了一个构建脚本,在伪代码中,该脚本如下所示: build = compile instrument if coverage <target name="build" depends="compile, coverage"/>
build =
compile
instrument if coverage
<target name="build" depends="compile, coverage"/>
<target name="compile"> .... </target>
<target name="coverage" depends="
create-coverage-dirs,
taskdef-cobertura"
if="build.with.coverage">
<cobertura-instrument ...> ... </cobertura-instrument>
</target>
<target name="create-coverage-dirs">
...
</target>
<target name="taskdef-cobertura">
...
</target>
coverage
任务也分为子目标:
coverage:
create-coverage-dirs
call-cobertura
编辑-我想表示不应运行覆盖率子目标
但是。。。我很难用ant ese“干净”地表达这一点
假设我可以使用depends
属性来指示。。。目标之间的依赖关系,我得到了如下结果:
build =
compile
instrument if coverage
<target name="build" depends="compile, coverage"/>
<target name="compile"> .... </target>
<target name="coverage" depends="
create-coverage-dirs,
taskdef-cobertura"
if="build.with.coverage">
<cobertura-instrument ...> ... </cobertura-instrument>
</target>
<target name="create-coverage-dirs">
...
</target>
<target name="taskdef-cobertura">
...
</target>
我可以在每个覆盖率子任务中添加if
属性,但我觉得这并不干净
所以问题是:
我的蚂蚁语是一种可怕的方言吗?我是在“把蚂蚁变成蚂蚁”吗
是应该这样使用if
,还是存在if和recurse
类型的属性
测试属性是否存在,而不是它是否为true或false。如果不想运行覆盖率目标,则不要定义属性build.with.coverage
从Ant 1.8.0开始,您可以使用属性扩展将属性响应为布尔值:
<target name="coverage" depends="
create-coverage-dirs,
taskdef-cobertura"
if="${build.with.coverage}">
测试属性是否存在,而不是它是否为真。如果不想运行覆盖率目标,则不要定义属性build.with.coverage
从Ant 1.8.0开始,您可以使用属性扩展将属性响应为布尔值:
<target name="coverage" depends="
create-coverage-dirs,
taskdef-cobertura"
if="${build.with.coverage}">
在这种情况下,我根本不会使用属性,而是完全依赖于depends
(对于这个任务,这对我来说似乎更自然):
...
...
在这种情况下,我根本不会使用属性,而是完全依赖于depends
(对于这个任务,这对我来说似乎更自然):
...
...
跟我重复一遍:Ant不是一种编程语言。事实上,在黑板上写100遍
Ant不是一种编程语言,所以不要这样认为。这是一个构建依赖关系矩阵
程序员很难对这个想法保持清醒的头脑。他们想告诉蚂蚁每一步以及什么时候该做。他们想要循环,如果语句。他们将求助于使用build.sh
脚本来调用Ant中的各种目标,因为您无法轻松编程Ant
在Ant中,您可以指定离散任务,以及哪些任务依赖于其他任务,并让Ant处理在何时何地执行任务
我想说的是,您通常不会将任务拆分为子任务,然后尝试调用。为什么?因为这是一个标准化目标名称的好方法。开发人员知道,clean
将删除所有构建的工件,compile
将运行
任务,test
将运行junit
测试。因此,您应该使用:cobertura
中的目标
编辑
我的问题是:我认为“覆盖率”与“优化”和“调试”相关,即构建风格。这就是我的困难所在:对于Java,覆盖率会导致编译步骤中额外的中间目标
我正在查看Corburta页面,而
任务(编译目标的一部分)中没有实际的更改
相反,您可以在已经构建的.class
文件上运行Corburtura,然后运行
任务。最大的变化是
任务,它现在必须包括对Corburtura JAR和插入指令的类的引用
我想你可以有一个corburtura
目标,或者你想叫它什么。这个目标运行插入指令的JUnit测试。这是你希望开发人员达到的目标,应该包含一个描述,说明它运行插入指令的测试
当然,如果不首先检测Junit测试,就无法运行检测后的Junit测试。因此,您的corburtura
目标将依赖于另一个工具。测试目标。此目标是内部的。运行build.xml
的人通常不会说“工具测试”没有运行这些测试。因此,此目标没有描述
当然,instrument.tests
目标依赖于要插入的.class
文件,因此它将依赖于运行
任务的编译
目标:
<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测试运行宏。我使用了页面上的内容来帮助编写大纲。完全未经测试,可能有很多语法错误:
<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不是一种编程语言。事实上,把它写在黑板上100遍
Ant不是一种编程语言,所以不要这样认为,它是一种构建依赖矩阵
程序员很难对这一想法了如指掌。他们想告诉Ant每一步以及什么时候应该完成。他们想要循环,if语句。他们会求助于使用build.sh
脚本来调用Ant中的各种目标,因为你无法轻松地编程Ant
在一个
<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>
$ ant -p
<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>
<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>