作者:冼志超,新炬网络高级技术专家。
EMMA 是一个开源、面向 Java 程序测试覆盖率收集和报告工具。它通过对编译后的 Java 字节码文件进行插装,在测试执行过程中收集覆盖率信息,并通过支持多种报表格式对覆盖率结果进行展示。
EMMA 收集的数据包括类覆盖率、方法覆盖率、块覆盖率和行覆盖率,这些数据以包为单位进行组织。
大多数功能测试中,测试人员一般不能直接得到被测源代码,源代码也不是测试人员关心的重点。在具体的测试过程中,功能测试人员一般以一个有意义的功能模块作为测试关心的重点,而能够反映一定功能含义的类和方法的覆盖率在功能测试中更有价值。因此,在功能测试中,类覆盖率和方法覆盖率是测试人员关心的重点,行和块覆盖率则作为测试的参考。
测试覆盖率报告中包含了两个方面的内容,测试覆盖的部分和未被测试覆盖的部分。尽管百分之百的测试覆盖率不能代表被测对象完全没有问题,但是测试覆盖的部分以及覆盖比率可以增加测试者对测试工作的信心,指导测试执行以及测试的方向。另一方面,当测试用例执行出现异常时,针对每个测试用例的测试报告还可以提供可疑代码的范围,为代码纠错提供帮助。
测试覆盖率报告中未覆盖的部分也同样有价值:
· 表明测试可能不完整,有些功能、代码没有被测试覆盖到。
· 为测试用例的设计提供指导建议。在覆盖率报告的指导下,测试人员有目的地与开发人员进行讨论,确定未覆盖部分是测试的空白还是不需要测试的部分。
· 帮助开发人员发现无用代码,为修改,完善代码提供依据。
在使用 EMMA 获得测试覆盖率过程中,类、方法等覆盖的百分比报告,可以方便测试人员更好的评估测试。测试人员通过对照覆盖率报告与测试用例设计文档,需求文档可以迅速找到测试的不足。通过与开发人员进行讨论,可以更好的评估测试力度,并指导进一步的测试。因此在功能测试中引入覆盖率信息,能够完善测试结果报告,确保测试质量和力度,保证测试按质、按量地完成。
EMMA覆盖率测试工具是由纯Java开发,可运行在任何支持JRE1.6+版本的系统内,包括Windows、Linux。
Emma覆盖率测试工具运行时需使用JRE,配置环境变量:
· JAVA_HOME:C:\Program Files (x86)\Java\jdk1.6.0_38
· Path:C:\Program Files (x86)\Java\jdk1.6.0_38\bin;
· CLASSPATH:.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;
配置好后,命令窗口中分别输入java –version和javac,出现如下图的信息,即为配置成功。
使用Tomcat部署开源JSPXCMS的演示站点,包含了新闻、图集、视频、下载、在线留言、人员招聘、BBS等模块。jspxcms是一个开源的、基于Java的内容管理系统(CMS),依托Java的开源精神和强大的企业级功能,致力于实现Java CMS网站制作、维护。
在执行插装操作之前,首先应该扩展 Java 虚拟机,即将 emma.jar 放到被测组件运行使用的JRE 目录下面作为 JRE 的扩展,以便 EMMA 能够被调用。 emma.jar 包含了 EMMA 核心功能模块的实现和 EMMA 运行时所需的类文件,这些文件是使用 EMMA 所必需的。
· 把emma.jar放到C:\Program Files (x86)\Java\jre6\lib\ext目录下;
· 把emma.jar放到示例工程项目lib目录下;
Emma.jar放置路径为:C:\apache-tomcat-6.0.29\webapps\jspxcms\WEB-INF\lib
EMMA使用基本步骤是:插桩(instr),运行,收集(ctl),报告(report)
EMMA生成文件目录:
插桩生成的二进制文件:jspxcms_coverage.em
收集覆盖率信息生成的二进制文件:jspxcms_coverage.ec
生成覆盖率报告的文件:jspxcms_coverage.html
EMMA 中提供了 “instr” 命令完成插装操作。插装操作可以面向 JAR 包、WAR 包、类文件和目录。
插桩前,启动应用服务。
在命令窗口中cd C:/Program Files/Java/jre6/bin/
(或直接配置emma.jar的classpath环境变量)
插桩命令:
参数 “m”代表插装后文件输出的模式。有三个值可供选择: “copy” ,“overwrite” 和 “fullcopy” 。其中,“copy” 和 “ fullcopy” 这两种模式将会改变插装文件所在的目录,并需要手动为其生成所需的包,使用起来比较复杂。“overwrite” 模式直接用插装后的文件覆盖插装前文件,使用方便。但是由于同一时间生成的文件只能插装一次,在 “overwrite”模式下,插装前的文件已经丢失,无法重复插装操作,因此在插装之前先将需要插装的文件和包进行备份。
参数 “ip” 和 “cp” 用来提供插装路径,其中 “cp” 用来指明一个文件夹, “ip” 指定单独的文件或者 JAR 包。
参数 “Dmetadata.out.file” 用来指定插装得到的元数据文件保存的路径。
命令中通过 “ix” 参数指定文件的包含和排除关系,其中在 “+” 符号后的文件为包含进的文件, “-” 后面的内容为排除在外的文件。支持多个+和-,用逗号分隔。
插桩成果结果显示:(580个类文件插桩成功)
完成插装操作以后,在指定的路径下会产生一些名为 “*coverage.em” 的文件,这些文件保存了插装的元信息,这些信息主要是记录插装过程中的插装点在被测代码中的位置。如果在插装过程中,指定这些文件到同一文件的话, EMMA 默认将元数据进行合并。如果未指定路径,或者希望得到独立的元文件,这些文件将分别产生在默认或指定的目录下。可以通过使用 “merge” 命令手动将这些元文件进行合并,保证生成的覆盖率报表的全面性。
命令:java emma merge -input path1>/coverage1.em,
在 “input” 后面的参数为待合并的文件名,在 “out” 后面的参数为合并以后的结果文件。
确保emma.jar已放在tomcat部署JSPXCMS的lib目录下,一般情况下,直接运行应用程序即可。EMMA会启动一个监听端口,用来后面收集信息(ctl)。这个端口是固定的,47653。
启动TOMCAT:
打开JSPXCMS网站,执行一系列功能测试操作。
执行收集命令前,应用服务需保持启用状态。
本地覆盖率数据收集命令:
收集成功显示: 收集到的信息被保存在 “coverage.ec” 中。
生成代码覆盖率报告命令:
执行成功会显示:
测试报告可以以 HTML ,文本和 XML 三种格式输出。
打开jspxcms_coverage.html,覆盖率的报告是以包、类、方法三级单位组织的。其中红颜色代表该覆盖率未达到满意的覆盖率标准:
下图是包com.jspxcms.common.fulltext类的执行情况:
下图是包com.jspxcms.common.fulltext类DefaultLuceneIndexTemplate.java的方法执行情况:
为得到独立的测试报告,需要在每次执行测试用例前,将内存中的执行信息清除。目前有两种方法支持清除记录,测试人员可在测试过程中,根据需要选择合适的方法。
· 每次运行完一个测试用例,重启 JVM 。这种方法能够完整的清除内存中记录的执行信息,但是每次重启 JVM 给测试带来很多麻烦。
· 使用 “coverage.reset” 命令,该命令可以在不重启 JVM 的情况下,清除内存中记录的方法、块、行的执行信息,但是无法清除类覆盖信息。如果用户关注的重点在方法的覆盖信息上,可以选择这种方法。
清除内存中覆盖率信息命令:
执行成功会显示:
下图可见,执行coverage.reset后,内存中记录的方法、块、行的执行信息被清除,但是无法清除类覆盖信息。
当完成所有单独执行测试用例后,测试覆盖信息可以被合并在一起,得到整个测试的覆盖报告。覆盖率结果文件通过 “merge” 命令合并 “*.ec” 文件实现的。
由于 EMMA 中测试覆盖率是通过与 “*.em” 文件关联获得代码信息的,因此当代码发生变化时,已经运行过的测试不必完全重复,只需将得到的 “*.ec” 文件合并(新得到的 “*.ec” 文件放在后面),然后关联最新的 “*.em” 文件即可得到代码变化后的覆盖率信息,这方便了 EMMA 支持版本变化的测试。在生成新的测试报告的时候,需要注意 “*.ec” 的时间一定要晚于 “*.em” 文件。
· 自动合并。如果生成的.ec文件名字相同,自动合并。
· 命令行合并:java -cp emma merge -input jspxcms1_coverage.ec, jspxcms2_coverage.ec -outfile jspxcms_coverage.ec
举例说明:(收集独立测试用例“搜索功能”的代码覆盖率数据,并定位其具体实现类和方法)
独立测试用例“搜索功能”执行前,如下图覆盖率为0%,被执行的类和方法同样为0:
在网站页面,执行搜索操作:
收集覆盖率信息,生成报告:
由上图可见,执行搜索测试用例后,1个类和4个方法被调用。进入查看明细:
从上图报告明细可见,搜索测试用例关联的类为FInfo.java。即是可通过测试用例反推定位找到具体实现的类和方法。
存在问题:
一般情况下,系统首页加载,系统登陆,页面跳转等情况可能会执行相关类和方法,故测试人员进入要测功能模块页面,未测试时,已经产生代码覆盖率数据。使用coverage.reset命令可清除方法、块、行执行信息,但无法清除类的执行信息。如果通过重启JVM实现清除类、方法、块、行执行信息,除了操作上较麻烦外,还因为对于一般大型项目web系统,在tomcat、websphere或weblogic启动时,应用程序的一些后台服务,配置、数据字典等相关类和方法已经执行,故重启JVM的方法同样可能存在独立测试用例未执行已经存在代码覆盖率数据。所以独立用例关联到的类可能会包含其他类。故如果需要收集独立测试用例覆盖率信息,在执行独立测试用例之前,确保类、方法的覆盖率率为0%。执行独立测试用例后,生成的覆盖率数据为干净的独立测试用例覆盖率数据。
在功能测试过程中,为每个单独的测试用例生成独立的覆盖率报告能够给测试过程带来很大的帮助:
· 当测试用例失败或者抛出异常时,可以通过覆盖率报告找到该测试用例对应的代码,这样就可以为测试人员提供可能出错代码的范围。这一报告不仅可以帮助测试人员在提交问题时更加详细的描述错误,提供更详细的信息,还可以为开发人员跟踪问题提供线索,缩短解决问题的周期。
· 测试人员可以从独立的测试报告中获得代码和功能模块的对应关系,更好的理解测试用例的作用。
· 独立的测试报告可以帮助测试人员改进测试用例的设计,删除重复的测试用例,将覆盖点较多的测试用例进行拆分。
上一篇:Mysql查询缓存研究
下一篇:浅析虚拟化环境网卡绑定模式