用ant进行快速开发

        敏捷开发的一个基础就是使用自动化的构建过程,而这又是依赖于构建脚本工具的。ant是一个基于java的优秀的构建工具,我相信网上关于ant的介绍是铺天盖地,而ant的使用方法最好就是看ant的手册,这里我想将的是ant的实际用途,千万不要为了用ant而用ant,工具的作用在于提高你的效率。
        首先是这样一个场景,在我去年用eclipse开发web application的时候,wtp还没有成熟,一直用lomboz,lomboz也是个不错的插件,但问题在于,在快速开发方面没有什么支持?什么是快速开发?我的理解是,所谓快速开发,是要保证开发人员对于开发环境和部署环境的区别是透明的,说的通俗点,我一旦改好代码,希望按个按钮就能把改好的程序跑起来马上测试一下(这方面wtp做的非常棒),但是对于web application跑一个用需要一个部署过程,还要起tomcat这里的容器。也就是说,我一旦改好代码,想测试一下的话,要做这么几件事情,首先进入开发的目录,然后确保是一个正确的web application的目录结构(这一点lomboz已经帮你做好了),然后把整个目录部署在容器中(其实可以修改容器的配置文件,把应用的位置指向开发环境,但是当时我还是小白,不知道可以这样,而且这会打乱容器的正常部署),最后启动容器。
        简直是太麻烦了!于是网上找了个tomcat的插件,这样就可以在eclipse中点击一下按钮,就把容器起来了,不用到控制台打命令。但这仅仅解决了最后一步,上面怎么办?
        用ant解决!写一个部署脚本,完成上面的步骤:
       <project name="deploy" default="all" basedir="." >
<property name="dest.dir" value="C:/Program Files/Apache Software Foundation/Tomcat 5.5

/webapps/AjaxSamples"></property>
<property name="class.dir" value="build/classes"></property>
<target name="copyClass">
    <copy todir="${dest.dir}/WEB-INF/classes">
        <fileset dir="${class.dir}">
            <include name="**/*"/>
        </fileset>
    </copy>
</target>
<target name="copyOther">
    <copy todir="${dest.dir}">
        <fileset dir="WebContent">
            <include name="**/*"/>
        </fileset>
    </copy>
</target>
<target name="all" depends="copyClass,copyOther">
</target>
</project>
         这个project有两个target,第一个是部署class字节码文件,第二个是部署其他文件。分成两个的原因是因为在开发环境,字节码文件有另外的输出目录。dest.dir是tomcat的部署目录,class.dir是开发环境字节码的输出目录,这样一旦改完代码,只需要做两件事情,第一,运行一下脚本,第二,启动tomcat,然后就能直接在浏览器测试了。而且tomcat支持热插拔,甚至不用重启tomcat,只要运行脚本即可。
        上述这个例子比较简单,而且似乎和敏捷开发没什么帮助,下面给个稍微复杂的例子,在开源社区有许多帮助完成持续集成(continous integration)的工具,比如cruisecontrol,luntbuild等,这些构建的运行是基于用户自己的构建脚本的。下面我就举个这样的ant脚本的例子。写分析一下持续集成应该做哪些任务。第一,从cvs上下载源码,第二编译源码,第三编译测试代码,第四运行测试案例(junit),第五输出测试报告,第六部署报告。这里我要加一个步骤,持续集成经常要查看一些进一步的测试情况,这里假定我们会用emma这个优秀的分析代码覆盖率的工具,所以我要加的步骤就是在编译完源码之后需要往源码的字节码注入emma内容的一个target,和最后输出并部署emma报告的target并在原来的做 junit的target中加入emma的jvm参数。下面是整个脚本:
 <project name="buildWithEmma" default="execute">
    <target name="init">
        <property name="src.dir" value="src"></property>   
        <property name="class.dir" value="bin"></property>       
        <property name="testsrc.dir" value="test"></property>
        <property name="testclass.dir" value="testBin"></property>
        <property name="lib.dir" value="lib"></property>
        <property name="reports.dir" value="reports"></property>
        <property name="junitReport.dir" value="${reports.dir}/junit"></property>

        <property name="bin.instr.dir" value="instrBin"></property>
        <property name="coverage.dir" value="coverage"></property>
        <property name="emma.enabled" value="true"></property>

        </property>
        <path id="class.main.lib">
            <pathelement location="${class.dir}"/>
            <fileset dir="${lib.dir}">
                <include name="**/*.jar"/>
            </fileset>
        </path>
        <path id="class.src">
            <pathelement location="${class.dir}"/>
        </path>
        <path id ="emma.lib">
            <pathelement location="${lib.dir}/emma.jar"/>
            <pathelement location="${lib.dir}/emma_ant.jar"/>
        </path>
        <taskdef resource="emma_ant.properties" classpathref="emma.lib" />
    </target>

   
    <target name="compileSrc" depends="init">
        <delete dir="${class.dir}"></delete>
        <mkdir dir="${class.dir}"> </mkdir>
        <javac srcdir="${src.dir}"
               destdir="${class.dir}"
               debug="on"
        >
        <classpath refid="class.main.lib"/>
        </javac>
        <copy todir="${class.dir}">
            <fileset dir="${src.dir}">
                <exclude name="**/*.java" />
            </fileset>
        </copy>
    </target>
    <target name="compileTest" depends="init">
        <delete dir="${testclass.dir}"></delete>
        <mkdir dir="${testclass.dir}"/>
        <javac srcdir="${testsrc.dir}"
               destdir="${testclass.dir}"
               debug="on"
        >
        <classpath refid="class.main.lib" />

        </javac>
        <copy todir="${class.dir}">
            <fileset dir="${src.dir}">
                <exclude name="**/*.java" />
            </fileset>
        </copy>
    </target>
    <target name="instrument" depends="compileSrc">
        <delete dir="${bin.instr.dir}"></delete>
        <delete dir="${coverage.dir}"></delete>
        <mkdir dir="${bin.instr.dir}" />
                <mkdir dir="${coverage.dir}" />
                <emma enabled="${emma.enabled}">
                    <instr instrpathref="class.src"
                        destdir="${bin.instr.dir}"
                        metadatafile="${coverage.dir}/metadata.emma"
                        merge="true">
                    </instr>
                </emma>
                <copy todir="${bin.instr.dir}">
                    <fileset dir="${class.dir}">
                        <exclude name="**/*.java" />
                    </fileset>
                </copy>
    </target>

    <target name="test" depends="compileTest">
        <delete dir="${junitReport.dir}" failοnerrοr="false"/>
        <mkdir dir="${junitReport.dir}"/>
        <junit fork="true" forkmode="once" printsummary="withOutAndErr"

errorproperty="test.error" showoutput="on">


            <!--Refer to metadata.emma to collect run information-->
            <jvmarg value="-Demma.coverage.out.file=${coverage.dir}/coverage.emma"/>
            <jvmarg value="-Demma.coverage.out.merge=false" />
            <!--Test support package-->
            <classpath location="${bin.instr.dir}" />

            <classpath location="${testclass.dir}" />

            <classpath refid="emma.lib" />

            <formatter type="xml" />
            <!--Batch test exclude inner class-->
            <batchtest todir="${junitReport.dir}" haltonfailure="no">
                <fileset dir="${testclass.dir}">
                    <include name="**/*Test.class" />
                </fileset>
            </batchtest>
        </junit>
    </target>
    <target name="junitReport" depends="test">
        <junitreport todir="${junitReport.dir}">
            <fileset dir="${junitReport.dir}">
                <include name="*" />
            </fileset>
            <report format="frames" todir="${junitReport.dir}" />
        </junitreport>
    </target>
    <target name="coverageReport" depends="test">
        <emma enabled="${emma.enabled}">
            <report sourcepath="${src.dir}"
            sort="+block,+name,+method,+class"
            metrics="method:70,block:80,line:80,class:100">
                <fileset dir="${coverage.dir}">
                    <include name="*.emma" />
                </fileset>
                <html outfile="${coverage.dir}/coverage.html"
                depth="method" columns="name,class,method,block,line" />
            </report>
        </emma>
    </target>

 

    <target name="execute"

depends="init,compileSrc,instrument,compileTest,test,junitReport,coverageReport">
    </target>
</project>
         由于部署junit报告和emma报告的过程和之前的一个例子相似,所以给出的脚本就不包含这两个部署过程了。关于emma的一些特定ant的任务,请大家自行查阅相关资料,本文的目的还是在于关注ant脚本的整个流程,如何让脚本帮助进行快速开发。事实上即时没有持续集成工具,这样的一个脚本已经实现了大部分的自动构建功能了。完全可以手动选择时间来运行这个脚本以构建完整的系统。
         最后我想说的是,ant是帮助你提高效率的,我们需要关注的不是ant如何使用,而是何时使用。你是否在你的琐碎的日常工作中想到用 ant来帮助你提高效率呢?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值