EMMA 覆盖率工具

来源:互联网 发布:番茄时间管理 知乎 编辑:程序博客网 时间:2024/05/16 06:14

EMMA 覆盖率工具 


1. EMMA 介绍


EMMA 是一个开源、面向 Java 程序测试覆盖率收集和报告工具。它通过对编译后的 Java 字节码文件进行插装,在测试执行过程中收集覆盖率信息,并通过支持多种报表格式对覆盖率结果进行展示。EMMA可以统计几种覆盖率:class,method,block, line。支持版本迭代的覆盖率统计


2. EMMA 使用
EMMA基本是四步曲:插桩(instr),运行,收集(ctl),报告(report)。下面分别详细的介绍下


2.1 安装
下载地址:http://sourceforge.net/projects/emma/files/emma-testing/


目前流行使用的是v2.1.*,因为支持ctl命令,否则 在进行收集时ctl命令无效


将emm.jar cp /usr/local/jdk/jre/lib/ext 下面,安装完成



2.2 插桩


Emma对于统计代码覆盖率的功能,可以是针对编译路径下的class文件,也可以是针对运行在jar包中的class文件,这一步的意义在于,对这些需要监控的class文件做标记,术语叫插桩。对于插桩的命令如果需要监控多个jar包的运行情况,可以使用逗号分隔,一次性插桩需要监控的jar包。


模板:

command:java emma instr -cp /usr/local//anrs/lib/anrs.jar -m overwrite -ix +com.* -Dmetadata.out.file=test.em




参数介绍:


-cp,指定插桩的路径,多个jar包可以用,分割


-m:输出模式


     overwrite:重新jar包,anrs.jar


     default:copy, 需要加上-d参数,指定输出路径。有插桩,才cp一份class到指定路径


     fullcopy:需要加上-d参数,指定输出路径。 不管有没有插桩,都cp一份class到指定路径


-merge:合并。


    default:yes。 如果metadata指定输出的文件一样,将两次插桩信息进行合并


    no。不合并两次插桩信息


-ix:指定需要插桩的class


   +com.*: + 指包含


   -com.*:-指排除


  支持多个+和-,用逗号分隔


这个功能对我们关注被改动的代码很有作用


-Dmetadata.out.file: 指定元数据(metadata)输出路径。默认是当前路径 


linux:

#:/root/java/jdk1.7.0_25/jre/bin/java emma instr -m overwrite -cp  /root/tomcat/apache-tomcat-7.0.59/webapps/bbs/WEB-INF/classes -Dmetadata.out.file=/root/coverage/coverage.em

插桩完成之后会在/root/coverage路径下面生成一个coverage.em文件,包含当次插桩的所有信息。对于多个jar包也可以多条命令分次插桩,如果指定的插桩文件coverage.em输出路径相同,则每一次的插桩文件和自动合并;



我们在测试过程中, 一般都会去更新几次jar包,并且我们希望统计出这个版本测试的覆盖率,我们就需要把几次的元数据进行合并


2.3 运行


一般情况下,直接运行应用程序即可。EMMA会启动一个监听端口,用来后面收集信息(ctl)。这个端口是固定的,47653。


如果我们的应用是多进程的,就会出现启动失败。


其实EMMA也提供了一个命令,进行端口设置:-Demma.rt.control.port=39123


还有host指定,-Demma.rt.control.host=192.168.22.22. default is localhost


这个参数需要加在程序启动命令里


EMMA还有简单的配置文件:java -Demma.properties=my.properties


my.properties format: tag=value


可以配置的参数参考:http://emma.sourceforge.net/reference/ch03s02.html#prop-ref.tables


 

   在对需要监控的class文件插桩完成之后,需要重启当前环境,用以加载最新的插桩后的class文件。

使用emma插桩后的class文件,加入了emma统计变量,这些变量的值就是统计代码覆盖率的依据这些代码不会产生脏代码




2.4 收集
一般有两种收集信息方法:


1. 程序退出,自动收集,在当前运行目录下生成coverage.ec


2. 命令行:


java -cp /usr/jdk/jdk1.6.0_23/jre/lib/ext/emma.jar emma ctl -connect localhost:47653 -command coverage.get,coverage.ec


 例子:#:/root/java/jdk1.7.0_25/jre/bin/java -cp emma.jar emma report -r html -sp /root/tomcat/apache-tomcat-7.0.59/webapps/bbs/WEB-INF/classes -in coverage.em,coverage.ec -Dreport.html.out.file=/root/coverage/index.html

/root/java/jdk1.7.0_25/jre/bin/java -cp emma.jar emma report -r html -sp /root/tomcat/apache-tomcat-7.0.59/webapps/bbs/WEB-INF/classes -in coverage.em,coverage.ec -Dreport.html.out.file=/root/tomcat/apache-tomcat-7.0.59/webapps/dycs/index.html




合并.ec文件


由于 EMMA 中测试覆盖率是通过与 “*.em” 文件关联获得代码信息的,因此当代码发生变化时,已经运行过的测试不必完全重复,只需将得到的 “*.ec” 文件合并(新得到的 “*.ec” 文件放在后面),然后关联最新的 “*.em” 文件即可得到代码变化后的覆盖率信息,这方便了 EMMA 支持版本变化的测试。在生成新的测试报告的时候,需要注意 “*.ec” 的时间一定要晚于 “*.em” 文件。


1. 自动合并。如果生成的.ec文件名字相同,自动合并。


2. 命令行合并:java  -cp /usr/jdk/jdk1.6.0_23/jre/lib/ext/emma.jar emma merge -input SM1.ec, SM2.ec -outfile SM.ec


.ec 文件需要按照时间从前到后排列,才能保证合并信息正确(参考网上说法。但我测试的结果发现,自动合并与merge合并的结果不一致,自动合并的结果更准确。所以最好使用自动合并)


默认合并为coverage.es。


貌似现在的版本outfile参数不起作用,都会合并为coverage.es


 






清除执行统计信息


如果我们想要每个测试用例的独立覆盖率报告,需要将内存中的执行信息清除掉。


目前有两种清除方法:


1. 重启应用


2. 命令行:reset


java  -cp /usr/jdk/jdk1.6.0_23/jre/lib/ext/emma.jar emma ctl -connect localhost:47653 -command coverage.reset


reset只能清除内存中记录的方法、块、行的执行信息,但是无法清除类覆盖信息。


2.5 report


command:


java -cp /usr/jdk/jdk1.6.0_29/jre/lib/ext/emma.jar emma report -r html -in anrs.em coverage.ec –sp src/-Dreport.html.out.file=coverage.html


参数介绍


-r: report type:html,txt,xml


-sp: sourcecode path


3. 会碰到的问题(来源于网上介绍,refer to 
<http://www.51testing.com/?uid-170805-action-viewspace-itemid-87390> 



3.1 issue1
"emma ctl:


coverage.get: RPC failure while executing [coverage.get]


Exception in thread "main" com.vladium.emma.EMMARuntimeException: coverage.get:


RPC failure while executing [coverage.get]


        at com.vladium.emma.ctl.CtlProcessor._run(CtlProcessor.java:242)"


 


需要在应用执行目录下进行插桩,就可以解决这个issue


3.2 issue2
Exception in thread "main" java.lang.NoClassDefFoundError: com/vladium/emma/rt/R


T


        at org.apache.jmeter.NewDriver.$VRi(NewDriver.java)


        at org.apache.jmeter.NewDriver.<clinit>(NewDriver.java)


errorlevel=1


 


由于java加载ApacheJMeter.jar包时ClassLoader顺序非预期,通过-


Xbootclasspath/p:E:\alibaba\tools\emma-stable-2.1-lib\emma.jar  强制优先加载emma.jar。


故修改应用启动脚本为(以jemeter为例)


%JM_START% %JM_LAUNCH%  -Xbootclasspath/p:E:\alibaba\tools\emma-stable-2.1-lib\emma.jar  %


JVM_ARGS% %ARGS%   -jar "%JMETER_BIN%ApacheJMeter.jar" %JMETER_CMD_LINE_ARGS%


 


4. 项目应用
4.1 项目特点
应用程序会启动多个进程,启动脚本也会执行jar包。---需要解决emma端口冲突


测试过程中,由于bug会修改代码,版本迭代。希望统计这些版本的整个覆盖率信息---emma支持多个版本的覆盖率统计


希望每个case都有自己独立的覆盖率统计信息,同时也要有整个的覆盖统计信息。


4.2 应用
每个case执行的步骤:


1. 判断是否更新了jar包


1.1 更新:插桩,指定同个文件名合并到一起


1.1.1 stop app


1.1.2 设置 EMMAPORT 环境变量


1.1.3 启动一个应用进程,指定EMMAPORT:-Demma.rt.control.port=$EMMAPORT


1.1.4 循环1.1.2 & 1.1.3,启动完所有的进程


1.2 未更新:


1.2.1 清除执行信息:


java  -cp /usr/jdk/jdk1.6.0_23/jre/lib/ext/emma.jar emma ctl -connect localhost:47653 -command coverage.reset


2. 执行case


3. 收集执行信息


3.1 把所有进程的执行信息收集到一个文件里


java -cp /usr/jdk/jdk1.6.0_23/jre/lib/ext/emma.jar emma ctl -connect localhost:47653 -command coverage.get,coverage.ec


例子:#:/root/java/jdk1.7.0_25/jre/bin/java -cp emma.jar emma report -r html -sp /root/tomcat/apache-tomcat-7.0.59/webapps/bbs/WEB-INF/classes -in coverage.em,coverage.ec -Dreport.html.out.file=/root/coverage/index.html



3.2 每个case需要有独立的执行信息


cp coverage.ec coverage_caseNo.ec


4. 生成报告


测试完这个版本后,生成报告

#:/root/java/jdk1.7.0_25/jre/bin/java -cp emma.jar emma report -r html -sp /root/tomcat/apache-tomcat-7.0.59/webapps/bbs/WEB-INF/classes -in coverage.em,coverage.ec -Dreport.html.out.file=/root/cov/index.html


原创粉丝点击