用 Ant 和 Maven 进行测试
这个像 JUnit 一样的框架的美妙之处还在于,它可以把整套测试作为 build 的一部分运行,不需要人工进行干预。随着越来越多的人把测试用例加入代码基(code base),整体的测试套件日益增长,形成一个极好的回归平台(regression platform)。更妙的是,Ant 和 Maven 这样的 build 框架已经加入了报告特性,可以归纳 Junit 批处理任务运行的结果。
把一组 Groovy 测试用例整合到某一个构建中的最简单的方法是把它们编译成普通的 Java 字节码,然后把它们包含在 Ant 和 Maven 提供的标准的 Junit 批命令中。幸运的是,Groovy 提供了一个 Ant 标签,能够把未编译的 Groovy 脚本集成到字节码中,这样,把脚本转换成有用的字节码的处理工作就变得再简单不过。例如,如果正在使用 Maven 进行构建工作,那么只需在maven.xml 文件中添加两个新的目标、在 project.xml 中添加两个新的相关性、在 build.properties 文件中添加一个简单的标志就可以了。
我要从更新 maven.xml 文件开始,用新的目标来编译示例脚本,如清单 8 所示:
清单 8. 定义 Groovyc 目标的新 maven.xml 文件
<goal name=”run-groovyc” prereqs=”java:compile,test:compile”>
<path id=”groovy.classpath”>
<pathelement path=”${maven.build.dest}”/>
<pathelement path=”target/classes”/>
<pathelement path=”target/test-classes”/>
<path refid=”maven.dependency.classpath”/>
</path>
<taskdef name=”groovyc” classname=”org.codehaus.groovy.ant.Groovyc”>
<classpath refid=”groovy.classpath”/>
</taskdef>
<groovyc destdir=”${basedir}/target/test-classes” srcdir=”${basedir}/test/groovy”
listfiles=”true”>
<classpath refid=”groovy.classpath”/>
</groovyc>
</goal>
上面代码中发生了以下几件事。第一,我定义一个名为 run-groovyc 的新目标。该目标有两个前提条件, java:compile 编译示例源代码, test:compile 编译普通的 Java-JUnit 类。我还用 <path> 标签创建了一个 classpath。在该例中,classpath 把 build 目录(保存编译后的源文件)和与它相关的所有依存关系(即 JAR 文件)整合在一起。接着,我还用 <taskdef> Ant 标签定义了 groovyc 任务。
而且,请您注意我在 classpath 中是如何告诉 Maven 到哪里去找 org.codehaus.groovy.ant.Groovyc 这个类。在示例的最后一行,我定义了 <groovyc> 标签,它会编译在 test/groovy 目录中发现的全部 Groovy 脚本,并把生成的 .class 文件放在 target/test-classes 目录中。
一些重要细节
为了编译 Groovy 脚本,并运行生成的字节码,我必须要通过 project.xml 文件定义两个新的依存关系( groovy 和 asm),如清单 9 所示:
清单 9. project.xml 文件中的新的依存关系
<dependency>
<groupId>groovy</groupId>
<id>groovy</id>
<version>1.0-beta-6</version>
</dependency>
<dependency>
<groupId>asm</groupId>
<id>asm</id>
<version>1.4.1</version>
</dependency>
一旦将脚本编译成普遍的 Java 字节码,那么任何标准的 JUnit 运行器就都能运行它们。因为 Ant 和 Maven 都拥有 JUnit 运行器标签,所以下一步就是让 JUnit 挑选新编译的 Groovy 脚本。而且,因为 Maven 的 JUnit 运行器使用模式匹配来查找要运行的测试套件,所以需要在 build.properties 文件中添加一个特殊标记,如清单 10 所示,该标记告诉 Maven 去搜索类而不是搜索 .java 文件。
清单 10. Maven 项目的 build.properties 文件
maven.test.search.classdir = true
最后,我在 maven.xml 文件中定义了一个测试目标( goal),如清单 11 所示。这样做可以确保 在单元测试运行之前,使用新的 run-groovyc 目标编译 Groovy 脚本。
清单 11. maven.xml 的新目标
<goal name=”test”>
<attainGoal name=”run-groovyc”/>
<attainGoal name=”test:test”/>
</goal>
最后一个,但并非最不重要
有了新定义的两个目标(一个用来编译脚本,另外一个用来运行 Java 和 Groovy 组合而成的单元测试),剩下的事就只有运行它们,检查是不是每件事都顺利运行!
在清单 12 中,您可以看到,当我运行 Maven,给 test 传递目标之后,会发生了什么,它首先包含 run-groovyc 目标(而该目标恰好还包含 java:compile 和 test:compile 这两个目标),然后包含 Maven 中自带的标准的 test:test 目标。请注意观察目标 test:test 是如何处理新生成的 Groovy 脚本(在该例中,是新 编译的 Groovy 脚本) 以及普通的 Java JUnit 测试。
清单 12. 运行新的测试目标
$ ./maven test
test:
java:compile:
[echo] Compiling to /home/aglover/dev/target/classes
[javac] Compiling 15 source files to /home/aglover/dev/target/classes
test:compile:
[javac] Compiling 4 source files to /home/aglover/dev/target/test-classes
run-groovyc:
[groovyc] Compiling 2 source files to /home/aglover/dev/target/test-classes
[groovyc] /home/aglover/dev/test/groovy/test/RegexFilterTest.groovy
[groovyc] /home/aglover/dev/test/groovy/test/SimpleFilterTest.groovy
test:test:
[junit] Running test.RegexFilterTest
[junit] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0.656 sec
[junit] Running test.SimpleFilterTest
[junit] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0.609 sec
[junit] Running test.SimplePackageFilterTest
[junit] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0.578 sec
BUILD SUCCESSFUL
Total time: 42 seconds
Finished at: Tue Sep 21 17:37:08 EDT 2004
结束语
在 实战 Groovy 系列的第一期中,您学习了 Groovy 这个令人兴奋的脚本语言最实用的应用当中的一个。对于越来越多开发人员而言,单元测试是开发过程的重要组成部分;而使用 Groovy 和 JUnit 对 Java 代码进行测试就变成了轻而易举的事情。
Groovy 简单的语法、内部的灵活性,使其成为迅速编写有效的 JUnit 测试、将测试整合到自动编译中的一个优秀平台。对于像我一样为代码质量发狂的人来说,这种组合极大地减少了我的 神经紧张,还让我可以得到我想做得最好的东西:编写“防弹”软件。快点行动吧
关于作者
Andrew Glover 是 Vanward Technologies 的 CTO,该公司位于华盛顿特区的大都会地区,公司的专业领域是自动测试框架的构造,该框架可以减少软件 bug 数量,缩短集成和测试的时间,提高代码的整体稳定性。
结束语
在 实战 Groovy 系列的第一期中,您学习了 Groovy 这个令人兴奋的脚本语言最实用的应用当中的一个。对于越来越多开发人员而言,单元测试是开发过程的重要组成部分;而使用 Groovy 和 JUnit 对Java 代码进行测试就变成了轻而易举的事情。
Groovy 简单的语法、内部的灵活性,使其成为迅速编写有效的 JUnit 测试、将测试整合到自动编译中的一个优秀平台。对于像我一样为代码质量发狂的人来说,这种组合极大地减少了我的 神经紧张,还让我可以得到我想做得最好的东西:编写“防弹”软件。快点行动吧
关于作者
Andrew Glover 是 Vanward Technologies 的 CTO,该公司位于华盛顿特区的大都会地区,公司的专业领域是自动测试框架的构造,该框架可以减少软件 bug 数量,缩短集成和测试的时间,提高代码的整体稳定性。
参考资料
Groovy 的下载地址是 Groovy open source project page,在那里,您还可以学习更多的知识,比如编译、单元测试、正则表达式等。
请勿错过作者在其 alt.lang.jre 系列 的“ Feeling Groovy”一文中对 Groovy 的第一次介绍。(developerWorks,2004 年 8 月)。
JUnit 的下载地址是 The JUnit home page。
DbUnit 的下载地址是 The DbUnit home page。
StrutsTestCase 的下载地址是 The StrutsTestCase home page。
Bruce Tate 是 Bitter Java 和 Better, Faster, Lighter Java 的作者,他是敏捷编程的鼓吹者,他有一个经常更新的 Blog,您可以常去看看。
Richard Hightower 和 Nicholas Lesiecki 合著的 Java tools for extreme programming 是 Java 平台上进行敏捷编程的一份实践者指南,其中有一章文章是关于“ Building Java applications with Ant”的。(摘自 developerWorks,2002 年 6 月)。
Just Groovy 是一个专门介绍 Groovy 的 Web 站点,对,就是Groovy!