EMMA,一个用于检测和报告 JAVA 代码覆盖率的开源工具,我们很多情况下在单元测试中用它来代码的用例覆盖率,今天我们讲一下如何在功能测试的时候用emma统计我们的测试用例覆盖了多少java代码。
Emma工作原理分析:EMMA对编译过的class文件作一个叫做插装(instrument)的处理,并生成一个插装信息文件coverage.em,这个文件记录了代码的版本信息,包、类、方法、块、行信息等;被插装过的class文件,在运行时,会触发EMMA中的方法运行,将代码运行的信息记录在JVM中,当JVM关闭时,EMMA将JVM中的代码运行信息输出到外部文件(如coverage.ec),然后用EMMA的生成覆盖率报告功能生成报告。
前提条件: 将emma.java加入到CLASSPATH环境变量中,即:set CLASSPATH=%CLASSPATH%;/*/*emma.jar
set CLASSPATH=%CLASSPATH%;D:\code.sources\emma-2.0.5312\lib\emma.jar
emma jar包的下载位置:http://sourceforge.net/projects/emma/files/
第一步:插装
EMMA 中提供了 “instr” 命令完成插装操作。对文件插装:java emma instr -m overwrite -ip fileDericty -Dmetadata.out.file=/home/xxx/emma/coverage.em
对Jar包插装:和对文件插装大致一样 java emma instr -m overwrite -cp xxxx.jar -Dmetadata.out.file=/home/xxx/emma/coverage.em
- D:\code\demo01\target>java emma instr -m overwrite -cp demo01.jar -Dmetadata.out.file=coverage.em
- EMMA: processing instrumentation path ...
- EMMA: instrumentation path processed in 172 ms
- EMMA: [2 class(es) instrumented, 4 resource(s) copied]
- EMMA: metadata merged into [D:\code\demo01\target\coverage.em] {in 203 ms}
对War包进行插装:试了几次都是EMMA: [0 class(es) instrumented, 0 resource(s) copied]不知道为何,暂时无解
选择性的插装:java emma instr -m overwrite -cp xxx.jar -ix +org.wstest.service.* -Dmetadata.out.file=/xxxx/emma/coverage.em。其中在 “+” 符号后的文件为包含进的文件, “-” 后面的内容为排除在外的文件
合并源数据的命令:java emma merge -input <path1>/coverage1.em,<path2>/coverage.em -out <path>/coverage2.em
第二步:收集覆盖率信息(产生ec文件)
java emma ctl -connect localhost:port -command coverage.get,/xxxx/emma/coverage.ec
执行java -jar demo01.jar 时,产生异常。分析确认由于java加载demo01.jar包时ClassLoader顺序非预期,通过-Xbootclasspath/p:-Xbootclasspath/p:D:\code.sources\emma-2.0.5312\lib\emma.jar 强制优先加载emma.jar。
- D:\code.temp\demo01\target>java -jar demo01.jar
- Exception in thread "main" java.lang.NoClassDefFoundError: com/vladium/emma/rt/RT
- at com.alibaba.demo.Demo01.$VRi(Demo01.java)
- at com.alibaba.demo.Demo01.<clinit>(Demo01.java)
- Caused by: java.lang.ClassNotFoundException: com.vladium.emma.rt.RT
- at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
- at java.security.AccessController.doPrivileged(Native Method)
- at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
- at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
- at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
- at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
- ... 2 more
- Could not find the main class: com.alibaba.demo.Demo01. Program will exit.
解决方案如下:
- D:\code.temp\demo01\target>java -Xbootclasspath/p:D:\code.sources\emma-2.0.5312\lib\emma.jar -jar demo01.jar
- EMMA: collecting runtime coverage data ...
- zhangsan
- lisi
- wangwu
- zhaoliu
- shenqi
- EMMA: runtime coverage data merged into [D:\code.temp\demo01\target\coverage.ec] {in 62 ms}
同时可以参考大师的文档:http://www.51testing.com/?uid-170805-action-viewspace-itemid-87390
针对assembly生成的jar, 样例如下:
- D:\code.temp\demo02.client\target>java -Xbootclasspath/p:D:\code.sources\emma-2.0.5312\lib\emma.jar -jar demo02.client-jar-with-dependencies.jar
- EMMA: collecting runtime coverage data ...
- welcome you, Hessian, from remote!
- EMMA: runtime coverage data merged into [D:\code.temp\demo02.client\target\coverage.ec] {in 46 ms}
java -Xbootclasspath/p:-Xbootclasspath/p:emma.jar emma instr -m overwrite -cp demo01.jar -Dmetadata.out.file=coverage.em
java -Xbootclasspath/p:-Xbootclasspath/p:emma.jar emma ctl -connect localhost:47653 -command coverage.get,coverage.ec
- Authority:
- /home/pc2/stanley_sum/pc2-1.1.2-t/pc2.deploy/pc2.authority.deploy/target/web-deploy/lib
- pc2.authority.deploy-1.1.2.jar
- pc2.common-1.1.2.jar
- pc2.server.biz-1.1.2.jar
- java -Xbootclasspath/p:-Xbootclasspath/p:emma-47654.jar emma instr -m overwrite -cp pc2.server.biz-1.1.2.jar -Dmetadata.out.file=coverage_biz.em
- java -Xbootclasspath/p:-Xbootclasspath/p:emma-47654.jar emma instr -m overwrite -cp pc2.common-1.1.2.jar -Dmetadata.out.file=coverage_common.em
- java -Xbootclasspath/p:-Xbootclasspath/p:emma-47654.jar emma instr -m overwrite -cp pc2.authority.deploy-1.1.2.jar -Dmetadata.out.file=coverage_authority.em
- Delivery:
- /home/pc2/stanley_sum/pc2-1.1.2-t/pc2.deploy/pc2.delivery.deploy/target/web-deploy/lib
- pc2.common-1.1.2.jar
- pc2.delivery.deploy-1.1.2.jar
- pc2.server.biz-1.1.2.jar
- java -Xbootclasspath/p:-Xbootclasspath/p:emma-47655.jar emma instr -m overwrite -cp pc2.server.biz-1.1.2.jar -Dmetadata.out.file=coverage_biz.em
- java -Xbootclasspath/p:-Xbootclasspath/p:emma-47655.jar emma instr -m overwrite -cp pc2.common-1.1.2.jar -Dmetadata.out.file=coverage_common.em
- java -Xbootclasspath/p:-Xbootclasspath/p:emma-47655.jar emma instr -m overwrite -cp pc2.delivery.deploy-1.1.2.jar -Dmetadata.out.file=coverage_delivery.em
- Subscription:
- /home/pc2/stanley_sum/pc2-1.1.2-t/pc2.deploy/pc2.subscription.deploy/target/web-deploy/lib
- pc2.common-1.1.2.jar
- pc2.server.biz-1.1.2.jar
- pc2.subscription.deploy-1.1.2.jar
- java -Xbootclasspath/p:-Xbootclasspath/p:emma-47656.jar emma instr -m overwrite -cp pc2.server.biz-1.1.2.jar -Dmetadata.out.file=coverage_biz.em
- java -Xbootclasspath/p:-Xbootclasspath/p:emma-47656.jar emma instr -m overwrite -cp pc2.common-1.1.2.jar -Dmetadata.out.file=coverage_common.em
- java -Xbootclasspath/p:-Xbootclasspath/p:emma-47656.jar emma instr -m overwrite -cp pc2.subscription.deploy-1.1.2.jar -Dmetadata.out.file=coverage_subscription.em
多个文件打包:
java -Xbootclasspath/p:-Xbootclasspath/p:emma-47655.jar emma instr -m overwrite -ip pc2.server.biz-1.1.2.jar -ip pc2.common-1.1.2.jar -ip pc2.delivery.deploy-1.1.2.jar -Dmetadata.out.file=coverage_all.em
【注意】针对war包的情况, 先用jar xvf *.war进行解包,再进行emma针对里面lib下面的jar文件进行插装, 将生产的emma文件放到外面,再打回成war包即可
第三步:生成覆盖率报告
java emma report -r html -sp /xxxx/xxxx/javaSources -in /xxx/xxx/coverage.em,/xxx/xxx/coverage.ec -Dreport.html.out.file=/xxxx/xxxx/coverage.html
使用命令生成报告:
java emma report -r html -in coverage.em,coverage.ec -Dreport.html.out.file=coverage.html
- D:\code.temp\demo01\target>java emma report -r html -in coverage.em,coverage.ec -Dreport.html.out.file=coverage.html
- EMMA: processing input files ...
- EMMA: 2 file(s) read and merged in 16 ms
- EMMA: writing [html] report to [D:\code.temp\demo01\target\coverage\coverage.html] ...
如果没有-sp参数和相应的java源代码路径,产生的报告将没有源代码显示。
同时可参考:http://www.365testing.com/bbs/thread-8428-1-1.html
权威:
1、打桩多个jar包
- java -Xbootclasspath/p:-Xbootclasspath/p:emma-47655.jar emma instr -m overwrite -ip pc2.server.biz-1.1.2.jar -ip pc2.common-1.1.2.jar -ip pc2.authority.deploy-1.1.2.jar -Dmetadata.out.file=coverage_all.em
2、运行测试
3、合并多个项目统计报告:
- [pc2@qa-qd-62-152 result]$ java emma report -r html -in coverage.em,coverage_all_Subscription.em,coverage_all.em,coverage.ec,coverage_all_Subscription.ec,coverage_all.ec -Dreport.html.out.file=coverage.html
- Taobao TCC: processing input files ...
- Taobao TCC: 6 file(s) read and merged in 149 ms
- Taobao TCC: /home/pc2/result/_files/changedfiles.html
- Taobao TCC: writing [html] report to [/home/pc2/result/coverage/coverage.html] ...
2010-12-17凌晨1.39分记录:
- Authority:
- /home/pc2/stanley_sum/pc2-1.1.2-t/pc2.deploy/pc2.authority.deploy/target/web-deploy/lib
- cp /home/pc2/emma/emma-47655.jar ./
- pc2.authority.deploy-1.1.2.jar
- pc2.common-1.1.2.jar
- pc2.server.biz-1.1.2.jar
- java -Xbootclasspath/p:-Xbootclasspath/p:emma-47655.jar emma instr -m overwrite -cp pc2.server.biz-1.1.2.jar -Dmetadata.out.file=coverage_biz.em
- java -Xbootclasspath/p:-Xbootclasspath/p:emma-47655.jar emma instr -m overwrite -cp pc2.common-1.1.2.jar -Dmetadata.out.file=coverage_common.em
- java -Xbootclasspath/p:-Xbootclasspath/p:emma-47655.jar emma instr -m overwrite -cp pc2.authority.deploy-1.1.2.jar -Dmetadata.out.file=coverage_authority.em
- java -Xbootclasspath/p:-Xbootclasspath/p:emma-47655.jar emma instr -m overwrite -ip pc2.server.biz-1.1.2.jar -ip pc2.common-1.1.2.jar -ip pc2.authority.deploy-1.1.2.jar -Dmetadata.out.file=coverage_all.em
- java -Xbootclasspath/p:-Xbootclasspath/p:emma-47655.jar emma ctl -connect localhost:47655 -command coverage.get,coverage_all.ec
- Delivery:
- /home/pc2/stanley_sum/pc2-1.1.2-t/pc2.deploy/pc2.delivery.deploy/target/web-deploy/lib
- cp /home/pc2/emma/emma-47656.jar ./
- pc2.common-1.1.2.jar
- pc2.delivery.deploy-1.1.2.jar
- pc2.server.biz-1.1.2.jar
- java -Xbootclasspath/p:-Xbootclasspath/p:emma-47656.jar emma instr -m overwrite -cp pc2.server.biz-1.1.2.jar -Dmetadata.out.file=coverage_biz.em
- java -Xbootclasspath/p:-Xbootclasspath/p:emma-47656.jar emma instr -m overwrite -cp pc2.common-1.1.2.jar -Dmetadata.out.file=coverage_common.em
- java -Xbootclasspath/p:-Xbootclasspath/p:emma-47656.jar emma instr -m overwrite -cp pc2.delivery.deploy-1.1.2.jar -Dmetadata.out.file=coverage_delivery.em
- java -Xbootclasspath/p:-Xbootclasspath/p:emma-47656.jar emma instr -m overwrite -ip pc2.server.biz-1.1.2.jar -ip pc2.common-1.1.2.jar -ip pc2.delivery.deploy-1.1.2.jar -
- Dmetadata.out.file=coverage_all_Delivery.em
- java -Xbootclasspath/p:-Xbootclasspath/p:emma-47656.jar emma ctl -connect localhost:47656 -command coverage.get,coverage.ec
- Subscription:
- /home/pc2/stanley_sum/pc2-1.1.2-t/pc2.deploy/pc2.subscription.deploy/target/web-deploy/lib
- cp /home/pc2/emma/emma-47657.jar ./
- pc2.common-1.1.2.jar
- pc2.server.biz-1.1.2.jar
- pc2.subscription.deploy-1.1.2.jar
- java -Xbootclasspath/p:-Xbootclasspath/p:emma-47657.jar emma instr -m overwrite -cp pc2.server.biz-1.1.2.jar -Dmetadata.out.file=coverage_biz.em
- java -Xbootclasspath/p:-Xbootclasspath/p:emma-47657.jar emma instr -m overwrite -cp pc2.common-1.1.2.jar -Dmetadata.out.file=coverage_common.em
- java -Xbootclasspath/p:-Xbootclasspath/p:emma-47657.jar emma instr -m overwrite -cp pc2.subscription.deploy-1.1.2.jar -Dmetadata.out.file=coverage_subscription.em
- java -Xbootclasspath/p:-Xbootclasspath/p:emma-47657.jar emma instr -m overwrite -ip pc2.server.biz-1.1.2.jar -ip pc2.common-1.1.2.jar -ip pc2.subscription.deploy-1.1.2.jar -Dmetadata.out.file=coverage_all_Subscription.em
- java -Xbootclasspath/p:-Xbootclasspath/p:emma-47657.jar emma ctl -connect localhost:47657 -command coverage.get,coverage_all_Subscription.ec
http://emma.sourceforge.net/faq.html
3.3. I have a large project consisting of several sub-projects. I would like to generate one coverage report for my entire project as well as individual reports for sub-projects -- is that possible?
As should be clear from Can you provide details on various intermediate data files used by EMMA ..., the key to making this possible is to keep EMMA metadata and coverage data files partitioned by sub-project:
-
instrument all sub-projects and obtain separate metadata files prj1.em, prj2.em, etc. That is, do not merge all of your metadata into a single global*.em file;
-
similarly, run tests and obtain coverage data files prj1.ec, prj2.ec, etc;
-
now, to report on a selected project only, generate a report based on, say, {prj1.em, prj1.ec} files. And to report on the entire codebase, report based on all available files {prj1.em, prj2.em, ..., prj1.ec, prj2.ec, ...}.
4、在cmd中执行java emma
在环境变量中设置:CLASSPATH=%JAVA_HOME%\jre\lib;D:\lib\emma.jar; 如果emma.jar没加,则上面-cp emma.jar可以去掉
在tomcat的bin下的catalina.bat中设置:set JAVA_OPTS=%JAVA_OPTS% %LOGGING_MANAGER% -Xbootclasspath/p:D:\lib\emma.jar
本文转自 tianya23 51CTO博客,原文链接:http://blog.51cto.com/tianya23/426490,如需转载请自行联系原作者