文章

如何使用Ant自动构建并测试你的java程序

这几天一直在尝试使用Ant构建自己的Project,找了很多很多的方法,最后终于大概明白这玩意怎么写了。

ant的构建是基于一个build.xml文件的,非常简单,在线build工具travis-ci的默认build工具也是ant,所以干脆先学一学ant。

把自己实验一的build.xml贴上来,并逐行加以一些解释,相信应该还是比较清楚的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
<?xml version = "1.0"?>
<project name = "Lab1-1170300206" default = "test" basedir = ".">
	<property name="src" location="src"/>
	<property name="lib" location="lib"/>
  	<property name="build" location="build"/>
	<property name="test" location="test"/>
	 <property name="report.html" value="${basedir}/build/junit/html" />  
   	 <property name="report.xml" value="${basedir}/build/junit/xml" />  
	<target name = "clean">
		<delete dir = "${build}"/>
	</target>
	<path id="master-classpath"> 
		<fileset dir="${lib}"> 
			<include name="**/*.jar"/> 
		</fileset> 
	</path>

	<path id="test-classpath"> 
		<pathelement path = "${build}/classes"/>
		<fileset dir="${lib}"> 
			<include name="**/*.jar"/> 
		</fileset>
	</path>

	<path id="junit-classpath"> 
		<pathelement path = "${build}/classes"/>
		<pathelement path = "${build}/testclasses"/>
		<fileset dir="${lib}"> 
			<include name="**/*.jar"/> 
		</fileset>
	</path>

	<target name = "compile" depends = "clean">
		<mkdir dir = "${build}/classes"/>
		<javac srcdir = "${src}" destdir = "${build}/classes" source = "1.8" >
			<classpath refid="master-classpath"/>
		</javac> 
	</target>
	<target name = "compiletest" depends = "compile"> 
		<mkdir dir = "${build}/testclasses"/>  
		<javac srcdir = "${test}" destdir = "${build}/testclasses" source = "1.8">
			<classpath refid="test-classpath"/>
		</javac> 
	</target>
	<target name = "test" depends = "compiletest">
		<mkdir dir="${report.html}" />  
       		<mkdir dir="${report.xml}" /> 	
		<junit fork="yes" printsummary="yes" haltonfailure="no">	
			<classpath refid="junit-classpath"/>	
			<jvmarg line="-ea"/>
			<batchtest fork="yes" todir="${report.xml}">								
				<formatter type = "xml" usefile = "true"/>	
				<fileset dir="${basedir}/build/testclasses">  
                   		 	<include name="**/*Test.class" />  
               			</fileset> 
			</batchtest>	                      
		</junit>
		<junitreport todir="${report.html}">  
           		<fileset dir="${report.xml}">  
                		<include name="*.xml" />  
            		</fileset>  
            		<report format="frames" todir="${report.html}" />  
        	</junitreport>
	</target>
</project>

<?xml version = "1.0"?>

这行代码没什么意义,就是提示xml的版本。

<project name = "Lab1-1170300206" default = "test" basedir = ".">

project 根标签,name属性表示的是项目的名字,default参数表示的是在控制台单独使用ant命令时,默认执行的工作。basedir参数表示的是ant脚本运行时的根目录,此处’.’表示的是将当前所在目录设置为根目录。所有构建文件都必须有且只有一个元素,并且至少有一个元素。

<property name="src" location="src"/>

property 定义类标签,能够定义一些常量值,需要注意的是,定义以后不能再修改,相当于一个final的声明。上面这句话定义了一个名为src的地址,引用时用${src}来进行调用。这些设置应该就是方便后面引用地址。

1
2
3
<target name = "clean">
		<delete dir = "${build}"/>
	</target>

target 执行标签,是ant中执行的最小单位,在终端中可以使用ant targetname来执行,比如说ant build, ant debug。以上代码表示一个名为“clean”的工作,该工作的作用是删除一个目录,目录的dir是${build}代表的目录地址。

1
2
3
4
5
<path id="master-classpath"> 
		<fileset dir="${lib}"> 
			<include name="**/*.jar"/> 
		</fileset> 
	</path>

path 根据Ant官网的文档,path标识表示一个能够被当作为CLASSPATH或者PATH的环境变量。一个path也可以被描述为一个文件资源的合集。如果想多次使用这样的一个文件资源合集,可以为其指定一个id。

<pathelement path = "${build}/testclasses"/>

pathelement 在path-like-structure中定义一系列目录,构建成一个文件资源目录。相当于可以被引用的source。也可以在”“中用;分隔多个不同的文件目录。

fileset fileset定义了一组文件,这些文件能够在以dir为根目录的文档树中被以特定规则所匹配。利用include能够包括给定需要包括的文件,用**, *代表任意目录,任意文件名。类似地,使用exclude能够将指定模式的文件排除。我们可以看到一个简单的命令结构是需要以

<命令名字> ​ 内容

的格式来进行编写的。

1
2
3
<target name = "compile" depends = "clean">
		<mkdir dir = "${build}/classes"/>
		<javac srcdir = "${src}" destdir = "${build}/classes" source = "1.8" >

mkdir 在指定dir目录生成一个文件夹。

depends 该属性标识执行当前target所依赖的target,在执行当前任务之前,ant会检测是否已经执行了depends中指定的target,如果没有,ant会先执行depends所指定的target。

javac 编译命令,该命令用于编译java源文件,其扫描源和目标目录以编译源文件,只有对应的.class文件不存在,或者.class文件已经过时才编译,所以我们在之前需要先执行一次clean命令。

其具有如下的属性:

属性 描述 必须与否
srcdir 源Java文件
destdir 存储类文件的目标
includes 必须包含的文件模式列表
includesfile 文件的每一行都被视为包含模式
excludes 必须排除的文件模式列表
excludesfile 文件的每一行都被视为排除模式
classpath 要使用的类路径
bootclasspath 引导类文件的路径
extdirs 已安装扩展的路径
encoding 编码源文件
nowarn 用于将-nowarn开关传递给编译器
debug 在编译期间调试文件
debuglevel 设置调试文件的级别
optimize 指示是否应使用优化编译源
deprecation 与弃用信息一起编译  
verbose 询问编译器是否有详细输出
depend 为支持它的编译器启用依赖关系跟踪
includeAntRuntime 是否在类路径中包含Ant运行时库
fork 是否在外部使用JDK编译器执行javac
executable javac可执行文件的完整路径
memoryInitialSize 设置初始内存大小
memoryMaximumSize 底层JVM的最大内存大小

<classpath refid="test-classpath"/>

classpath 用于引入jar包以及一系列所需的class文件目录。

refid 用于引用前面声明过的对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
<target name = "test" depends = "compiletest">
		<mkdir dir="${report.html}" />  
       		<mkdir dir="${report.xml}" /> 	
		<junit fork="yes" printsummary="yes" haltonfailure="no">	
			<classpath refid="junit-classpath"/>	
			<jvmarg line="-ea"/>
			<batchtest fork="yes" todir="${report.xml}">								
				<formatter type = "xml" usefile = "true"/>	
				<fileset dir="${basedir}/build/testclasses">  
                   		 	<include name="**/*Test.class" />  
               			</fileset> 
			</batchtest>	                      
		</junit>

junit 这里就是我们跑junit测试文件的target了。该任务将会基于JUnit testing framework运行编写好的测试样例。Ant官方文档提示

需要使用Junit, 必须有junit.jar文件,你可以将junit.jar 和ant-junit.jar加入ANT_HOME/lib,或者不要将它加入lib中,将其加入你的CLASSPATH当中。

更多内容请参考apache Ant JUnit官方文档

本文在此处使用的就是后者指定的方法。

fork 该属性表示在一个新的虚拟机中运行我们的junit target。这个设置和vmarg有关,只有这个属性的value是yes,vmarg line = “-ea”才会有效

vmarg 虚拟机的设置,在试验中需要一个”-ea”的value开启断言机制

batchtest 事实上,ant支持两种方式进行junit测试。第一种方式是对每一个test.java文件进行测试,第二种就是使用batchtest批量对test.java文件进行测试。

formatter 定义测试结果的输出格式

1
2
3
4
5
6
7
	<junitreport todir="${report.html}">  
           		<fileset dir="${report.xml}">  
                		<include name="*.xml" />  
            		</fileset>  
            		<report format="frames" todir="${report.html}" />  
        	</junitreport>
	</target>

junitreport 定义一个junitreport task,用于输出相关的测试结果。这个东西我没有仔细研究,其可以将前面生成的xml测试报告转换成html格式。更多内容请看JunitReport

先写这么多,以后遇到了问题再增加

本文由作者按照 CC BY 4.0 进行授权