单元测试中的持续性能管理
开发中CPM的先决条件是具备一套单元测试用例;你的单元测试框架越健壮,那么得到的结果就越好。在这个例子中,将说明怎样集成单元测试性能分析,这用到了Apache Ant作为建造工具,和Quest软件的JProbe作为性能分析工具。
Apache Ant的中心是建造的XML文件,典型的名字为build.xml。这个文件包含了一套目标,当被Ant调用时,执行一系列特定动作。通用的目标包括如下方面:
- 初始化(init):通过执行创建构造和分发目录这样一些动作来初始化建造环境。
- 清除(clean):通过执行删除或移除现有的构造和分发目录这样一些动作从一个先前的建造中清除所有的工作。
- 编译(compile):编译源代码并保存到一个建造目录。
- 分发(dist):创建分发文件,例如一个JAR,包含已编译的源代码,以及所有企业级部署所需的WAR和EAR文件。
- 文档(docs):为代码建立JavaDoc文档。
- 测试:执行单元测试,tongchang 使用JUnit的Ant任务。
在这个CPM用例中,需要修改建造脚本,将包括一个新的目标,可运行JProbe 分析器(代码,覆盖,和内存),分析单元测试。JProbe提供了开箱即用的功能,可与Ant(和Maven)集成单独和批测试的执行,同时可生成报告。 但是对于CMP的目标,粒度还是粗糙。所以,需要创建了一个工具集,用于扩展JProbe/Ant的集成,可以方便地动态生成和导入分析建造脚本,并可创 建一个单独的报告,总结所有测试用例的结果。
集成JProbe代码,覆盖,和内存等的分析的工作流程要点如下:
1 安装JProbe CPM工具集
2 修改建造脚本并执行JProbe预处理器
3 导入生成的脚本
4 调用性能分析Ant目标
假设JProbe CPM工具集已经安装在c:\jprobe-ent目录下,在build.xml文件中增加下面这段必需的部分:
<!-- CPM properties -->
<property name="cpm.build-test.dir" value="${build-test.dir}"/>
<property name="cpm.junit.results.dir" value="test-results"/>
<property name="cpm.toolkit.home" location="C:\Program Files\JProbe CPM Toolkit" />
<property name="cpm.package.filters" value="com.yourcompany.*,com.outsourcedcompany.*" />
<!-- Setup a CLASSPATH that includes your application and test cases build directories -->
<path id="cpm.classpath.test">
<path refid="classpath"/>
<pathelement location="${build.dir}"/>
<pathelement location="${build-test.dir}"/>
</path>
<!-- Setup the Preprocessor's CLASSPATH -->
<path id="classpath.preprocessor">
<fileset dir="${cpm.toolkit.home}" includes="lib/*.jar"/>
</path>
<!-- Execute the JProbe Preprocessor -->
<java classname="com.javasrc.anttools.JProbePreprocessor">
<sysproperty key="src.dirs" value="${src.dir};${src-test.dir}" />
<sysproperty key="jprobe.home" value="${jprobe.home}" />
<sysproperty key="jprobe.build.dest" value="${cpm.toolkit.home}\jprobe.xml" />
<classpath refid="classpath.preprocessor"/>
</java>
<!-- Import the generated set of Ant tasks -->
<import file="${cpm.toolkit.home}\jprobe.xml" />
因为这是一个高级别的任务,它将会在所有任务之前执行。生成的jprobe.xml文件包含了下面这些新任务:
- performance-unit-tests.init:初始化性能单元测试环境;这依赖构造文件中存在的三个任务:clean, init, and compile.debug
- performance- unit-tests.execute:通过执行这些附加产生的Ant目标执行所有的性能单元测试:coverageunit-tests, memory-unit-tests, and performance-unit-tests;再加上执行generate-performance-report 任务生成一个XML性能概要文件和一个HTML报告
- generate-performance-report:由performanceunit-tests.execute目标调用;解析所有每个由JProbe生成的报告并创建一个单独的集合报告
为了获得行级分析信息,代码必须在调试模式下编译。下面说明了怎样修改你的Ant编译目标,假设你的编译目标如下所示:
<target name="compile" depends="init" description="compile the source">
<!-- Compile the java code from ${src} and ${src.test} into ${build}-->
<javac destdir="${build}" >
<src path="${src}" />
<src path="${src.test}" />
<classpath refid="classpath"/>
</javac>
</target>
创建调试编译目标并作如下修改(粗体):
<target name="compile.debug" depends="init" description="compile the source " >
<!-- Compile the java code from ${src} and ${src.test} into ${build}-->
<javac debug="on" destdir="${build}" >
<src path="${src}" />
<src path="${src.test}" />
<classpath refid="classpath"/>
</javac>
</target>
build.xml文件中增加的信息可以调用JProbe预处理器。JProbe预处理程序会从头到尾扫描你的源代码(在src.dirs属性中以分号分 隔的源代码目录列表)寻找按照JUnit命名规范,也就是以Test结尾的类。例如:MetricTest就是在工程中的一个测试类。对于每一个测试 类,JProbe预处理程序会识别所有测试方法,根据JUnit命名规范,所有的测试用例方法都会定义为加上test前缀并返回void。例 如,testRange()就是测试用例方法之一。JProbe预处理程序加上那些测试方法到分析套件。如果你按照标准的命名规范,那么JProbe会为 你所有的测试用例生成一个JProbe性能分析数据。
图1 说明预处理程序在CPM工作流程中的角色
图1 JProbe预处理程序工作流程