可以检查单元测试覆盖范围的分析工具
分析工具可以帮助程序员构建健壮的单元测试套件。迄今为止,完成这一工作主要有两种方法:
使用静态分析以尝试自动生成单元测试套件
使用静态分析来确定单元测试套件对程序功能的覆盖范围到底怎么样
目前有几种试图自动从代码产生单元测试的免费工具,但大多数担任这项任务的免费工具还处于起步阶段。其中一些比较有希望的是 JUnitDoclet 和 JUB(“JUnit test case Builder”的缩写),可在 SourceForge 上得到它们(参考资料一节提供了它们的链接)。
关于这些类型的工具,要牢记的要点是:适宜应用于通过测试更新旧代码。当构建新项目时,它们的作用不大。
为什么会这样呢?因为新项目应该与项目上的单元测试是一前一后构建的。开发单元测试是构建设计的强有力的方法;针对组件的 API 是在编写测试时隐式地为它们设计的。此外,以这种风格进行设计向设计师提供了即时的反馈。糟糕的设计将非常难于编写测试!并且,任何分析工具在确定为程序编写什么测试这方面,都很难做得象设计师那样好。
第二种分析工具分析程序及其单元测试,并确定测试能在多大范围内覆盖程序。与刚才提到的第一类工具不同,此类工具对每个项目都是有用的。实际上,极端编程团队可以考虑将此类工具集成到他们的代码提交过程中。那么,他们不仅能够防止代码在通过所有测试之前被提交,而且可以防止代码在未经测试的情况下提交!不仅懒惰会导致测试覆盖范围偏小,错误也可能导致同样后果,因此,此类强制措施对任何技能(和完整性)级别的程序员都有用。
Clover 是一种可以执行此类分析的新的并且特别有希望的工具。Clover 是 Ant 的插件,Ant 是 make 的流行的、全 Java 的替代物。Clover 是商业工具,但它可以免费用于开放源码项目。
Clover 分两阶段过程进行工作。首先,它在编译时检测代码。然后,在测试时将有关测试的运行信息写到用来生成报告的数据库中(通过 GUI、网页或在控制台中)。
将 Clover 集成到使用 Ant 的现有项目中很简单。这涉及调整项目的 build.xml 文件以添加几个在编译、记录测试和生成报表期间检测代码的目标。例如,假定我们有一个带构建和编译目标的 build.xml 文件。我们所必须做的全部工作是将 Clover JAR 文件放到我们的 Ant 库目录中,并如下所示扩展 build.xml 文件(Clover 用户指南中提供了这些和类似于 Ant 目标的信息;为了方便,我在这里包括了它们):
清单 3. 扩充 Ant build.xml 文件以使用 Clover
<property name="clover.initstring" value="/tmp/mycoverage.db"/>
<target name="with.clover">
<property name="build.compiler"
value="org.apache.tools.ant.taskdefs.CloverCompilerAdapter"/>
</target>
<path id="clover.classpath">
<pathelement path="<CLOVER_HOME>/lib/clover.jar"/>
<pathelement path="<CLOVER_HOME>/lib/velocity.jar"/>
</path>
<target name="clover.report">
<java classname="com.cortexeb.tools.clover.reporters.html.HtmlReporter">
<arg line="--outputdir /tmp/clover_html --showSrc --initstring
${clover.initstring} --title 'My Project'"/>
<classpath refid="clover.classpath"/>
</java>
</target>
特性 clover.initstring 指定了一个文件,有关 Clover 覆盖范围的数据将写入这个文件中。目标 with.clover 用来在执行其它目标(如 compile 和 test)时打开 Clover。clover.report 目标用来接收累积的覆盖范围数据并生成报告。
在上面的代码中,我们将生成 HTML 报告。我们也可以生成文本报告(对于提供给脚本以确定测试的覆盖范围是否可接受非常有用)和基于 Swing 的报告。
设置 clover.classpath 是必要的,以便报告生成器目标知道到哪里找到它所需要的所有类。但是,放在类路径中的第二个 JAR 文件(velocity.jar)只有在生成 HTML 报告时才是必需的。一旦完成了上述工作,可以用以下命令生成 Clover 报告:
$ ant with.clover compile test
$ ant clover.report
是这么简单。请查阅流行的编码工具 JBoss 和 Ant 的在线 Clover 报告,以获取一些样本输出。(您可以在参考资料一节找到更多有关这些内容的下载信息和其它信息。)
两种方法的结合
本文中讨论的工具突出了一些可以将程序分析和单元测试一起使用的方法,以提供比单独执行任何一种方法都更有效的不变量检测。这些技术只代表了所有可能技术的冰山一角。
将来,其它工具可能会提供更强有力的单元测试能力。例如,类型推断(type-inference)引擎和优化编译器可以从现有的单元测试推断线索、UML 生成工具可以从测试构造各种图表(不仅是类图)等等。对于合并这些方法以获得更佳的代码构建和故障诊断而言,还存在着巨大的空间可以进行创造性开发和实验。
请记住每种方法的属性及其长处:
单元测试能够演示程序在特定的运行期是如何运转的;还能说明执行的常用路径。
分析工具能够检查所有可能运行的程序的某些特定属性。
每种方法的长处都可以用来弥补另一种方法的潜在弱点。
下一次,我们将研究增强的单元测试的另一条路径,并了解一些新的工具,它们可用于帮助您在 GUI 上开发单元测试。
参考资料
请单击文章顶部或底部的讨论参与本文的论坛。
了解所有关于 Daikon(用 C/C++ 和 Java 前端进行动态不变量检测的原型实现)的内容,并从 Daikon 网站下载它。
请查阅 Clover user guide 以获取更多关于该工具的信息,该工具用来发现未被执行的代码部分,并确定何处的代码未经足够测试。
Clover 与 Ant(基于 Java 的构建工具)紧密地集成在一起,如果您还没有副本,请下载一个。
JUnitDoclet 是使用 XDoclet 的开放源码单元测试生成工具。
单元测试是极端编程的关键实践。在 Roy Miller 的 developerWorks 专栏 Demystifying Extreme Programming 中了解关于所有极端编程实践的更多信息。您也可以从 developerWorks Demystifying Extreme Programming 论坛获得 Roy 关于您 XP 问题的解答。
另一种开放源码生成工具是 JUB(JUnit 测试用例构建器),可从 SourceForge 获得。
可以在 JUnit 网站上找到更多扩充单元测试的工具。
Nicholas Lesiecki 在其文章“Test flexibly with AspectJ and mock objects”(developerWorks,2002 年 5 月)中介绍了关于测试用例独立性的问题,并向我们展示了如何使用仿真对象和 AspectJ 来开发准确而又强壮的单元测试。
Erik Hatcher 在其文章“Automating the build and test process”(developerWorks,2001 年 8 月)中,向您展示了他是如何修改流行的 Ant1.3 和 JUnit 测试框架,以实现构建和测试过程的完整的、定制的自动化。
WebSphere 开发者园地在“Application Quality Assurance:Unit Testing”中提供了一篇关于用 JUnit 进行单元测试的好文章。
“Debugging and Unit-Testing Server-Side Web Applications”也来自 WebSphere 开发者园地,它描述了包含迭代调试和交互式单元测试的服务器端 Web 开发方案。
下载 DrJava,这是一个免费的、轻量型的开放源码 Java IDE,具有集成的读-计算-打印(read-eval-print)循环、调试器和 JUnit 支持。
阅读 Eric Allen 的诊断 Java 代码专栏的所有文章,包括“Designing‘testable'applications”。
在 developerWorks Java 技术专区上可找到关于 Java 技术的数百篇文章和教程。