how to do java application’s code coverage with emma?

本文主要讨论如何用emma给Java Application做代码覆盖,区别于java单元测试的code coverage, Java Application一直处于运行状态,所以不能暴力的强行kill进程来收集代码覆盖数据,所以本文梳理下网络上的相关文章,整理下过程,并记录下尝试过程中一些常见问题的解决:

基本步骤分为五步:

(1)修改编译选项:

将编译的选项设置为debug启用,同时要注意debug的level.例如maven compiler默认就启用了debug但是没有将debug的level都设置进去,所以这里注意设置启用和启用的级别。例如对于maven项目中的compile plugin: (如果使用了progard进行混淆,则去掉混淆)

<configuration>
<debug>true</debug>
<debuglevel>lines,source</debuglevel>
</configuration>

(2) 注入:
注入coverage信息,可以使用-ix来过滤指定包:
java emma instr -m overwrite -cp server.jar -ix +com.server* -Dmetadata.out.file=coverage.em

note:

2.1 其中在 “+” 符号后的文件为包含进的文件, “-” 后面的内容为排除在外的文件,例如

-ix +com.foo.*,-com.foo.test.*,-com.foo.*Test*

2.2 要支持EMMA,需要复制emma.jar到lib目录,记得修改权限,例如:jdk1.7.0_60/jre/lib/ext/emma.jar

2.3 有时候加上过滤条件导出并没有生效,显示过滤的文件少了,但是产生的coverage.em基本没有变,可以删掉原先的,估计有merge操作。

(3)修改应用启动的jvm参数并启动应用:

3.1 修改启动应用的jvm参数:
-Demma.rt.control=true

为什么要增加这项,可以查看代码:默认是不启动实时收集功能。

IProperties appProperties = getAppProperties();
if (appProperties != null) {
String property = appProperties.getProperty("rt.control", "false");
enableController = Property.toBoolean(property);
}

if (enableController) {
int port = 47653;

if (appProperties != null) {
String property = appProperties.getProperty("rt.control.port");
if (property != null) {
try {
port = Integer.parseInt(property);
} catch (NumberFormatException ignore) {
System.err
.println("ignoring malformed [rt.control.port] value: "
+ property);
}

ps: 还存在其他很多参数,例如-Demma.coverage.out.file=/var/coverage.ec控制输出文件,-Demma.rt.control.port=12345,用来控制端口

3.2 启动,并查看log来确认是否正常:

应该存在2行log:其中第二行对应3.1要解决的问题。

EMMA: collecting runtime coverage data ...
EMMA: runtime controller started on port [47653]

其中,如果启动失败并提示class format错误,这是应用是JDK1.7编译的,而之前注入使用的emma的注入方式应该是不兼容的,所以可以通过增加JVM启动参数来解决:
1.7使用-XX:-UseSplitVerifier  如果是1.8使用-Xverify:none

(4)执行测试用例,然后使用命令收集数据:

java emma ctl -connect localhost:47653 -command coverage.get,coverage.ec

假设需要合并之前的,执行命令:

java emma merge -input coverage1.ec,coverage2.ec -out coverage.ec

PS: 也可以支持em的Merge.

(5)结合(2)产生的em和(4)产生的ec文件以及源代码的路径产生html报告:

java emma report -r html -sp /xxxx/xxxx/src/main/java -in coverage.em,coverage.ec -Dreport.html.out.file=coverage.html

这里需要注意的是源代码要和产生的统计信息一致,否则假设源代码当中的一个文件已经重命名,那么在html报告中还是提示找不到源文件。

实际测试中,我们还会应用单元测试,产生覆盖率,然后可以与上述产生的覆盖率合并。-in 支持传多个ec,em.

对于单元测试如何产生覆盖数据,可以直接配置EMMA的maven插件,然后使用mvn emma:emma来产生在target目录:

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>-XX:-UseSplitVerifier</argLine>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>emma-maven-plugin</artifactId>
<version>1.0-alpha-3</version>
</plugin>

 

PS:

通过上面可知,对于Coverage数据的过滤只有在注入阶段,在报告阶段并没有,好在本人同事对emma.jar进行了二次开发(emma_rar),支持在上面的第五步Report阶段过滤Class/Package。

具体命令:

java emma report -r html  -props filter.txt   -sp /xxxx/xxxx/src/main/java -in coverage.em,coverage.ec -Dreport.html.out.file=coverage.html

filter.txt 文件内容的格式可以是report.html.filter.class或者report.html.filter.package,例如示例:

report.html.filter.class=com.Tp.java,com.Constants.java   //多个类用,分割。

这里一定要注意的是:

(1)如果是内部类的过滤,一定不要带上外部类的名字,比如不应该是outer.inner.java,而应该是inner.java.这个可以查看EM文件的内容获知。

(2)支持正则表达式。

Notes:

(1) debug log: -Dverbosity.level=trace1

以上即为整个过程的记录以备忘!

 

Translate: 深入了解Java社区进程

Java语言发展初期,Sun Microsystems公司清楚意识到:Java若想成功,必须由社区需求驱动起来。正因如此,Java社区进程(JCP)得以建立。时至今日,JAVA语言推出已有17个年头,而JCP也建设了14年。目前JCP仍然发展良好。

JCP执行委员会监管JCP及JCP驱动下Java技术本身的发展和演化。现在有两个执行委员会,分别面向Java SE/EE和Java ME,计划在未来两年合并。

每个执行委员一般会由16名成员构成,包括:技术提供商,如Oracle、IBM和诺基亚;技术使用者,如瑞士信贷和高盛投资公司;Java用户组,例如巴西和伦敦用户组;个人,例如Werner Keil。

参与JCP必须先成为执行委员会一员并签署Java规范参与协议(JSPA)(更多参与JCP的相关信息参考www.jcp.org/en/participation/membership)。JCP赋予个人、组织和公司成员主持或参与Java规范请求(JSR)的权利。JSR是JCP完善自身或在Java领域引入新技术的流程。例如:Java相关的JSR就包括JSR 335 (Lambda项目),JSR 310 (时间、日期API), JSR 337(Java 8).以及上面提到的合并两个执行委员会的JSR 355

执行委员会会议一般是月度会议。除了三次面向全球、自愿参与的面对面会议,大多数会议都采用电话会议形式。下次会议定于9月份在捷克共和国首都布拉格市由德国电信主持召开。详情可查看JCP会议完整的日程表 jcp.org/en/whatsnew/calendar。

这次月度会议是2012年7月31日。

Java ME执行委员会需要参加的会议较少,这可能是Java ME地位被削弱所致。究其原因,在于移动应用中iOS本地应用程序和基于Java的可替代它的Andorid等的影响日益提高。

随着会议不断召开,一些JSR目前的阶段是:

JSR 359 (SIP Servlet):于昨天投票截至;

JSR 358 (Revisions to JCP);7月份投票截至;

JSR 340 (Java Servlet 3.1 Spec):进入初步草案审阅阶段;

JSR 341 (Expression Language 3.0 for JSP’s);投票在今天开始;

JSR 355 (JCP EC Merge):已经处于公开审阅阶段,最终草案已经制定,最终的表决投票将在今天开始。

2011年10月制定的JCP执行委员会成员规章V 2.1(The JCP EC Standing Rules 2.1)规定:出席的定义是成员出席面对面会议。规章同时也规定:如果一个成员连续两次缺席会议将失去选举权;12个月内连续缺席2/3的会议将取消成员资格。

SK电信和三星在最近8次会议中缺席了7次,已经达到上面规定提到的数量:12个月内10次会议的2/3。所以他们很可能失去成员资格。当然,JCP主管Patrick Curran可以法外开恩,但是目前来看没有什么理由如此。

Aplix的John Rizzo指出Oracle在Java Me执行委员会已经很久没有大作为。所以他们要承担部分责任,Patrick 同意把这个意见反映给Oracle。 美国电话电报公司(AT&T )也快被取消会员资格,因为前8次会议只参加了2次。如果今年再缺席一次,资格就会不保。

鉴于打印机业务是Java ME的主要应用之一,所以有传言三星的打印机部门会被重新被纳入JCP成员。

经过JSR355合并两个委员会之后,一些成员资格将被取消,具体实施计划如下:

  • 今年将除去两个重复的席位 – Oracle 和 IBM;
  • 每个新成员仅服务一年;
  • 2013年,额外减少3个候选席位和2个批准席位,所有成员都要重新参与竞争;
  • 会员任期将从3年减至2年;
  • 因为不得不换届,投票在50%以上的将获得2年任期,50%以下的一年,50%的由随机数决定。

JCP年度奖也在讨论中,提名工作在这星期结束,年度奖分为三类:

  • 年度JCP成员
  • 规范杰出主持者
  • 最重要Java规范请求

获奖者名单将在2012年10月2日三番市召开的JavaOne会议上公布。JCP接下来几个月的重要主题是JSR358(“JCP主要修订”)。相比较 JSR355用来处理执行委员会合并事宜,JSR358致力于简化JCP,让JCP更易吸纳成员,简化主要针对的是JSPA。经常有很多抱怨指出JSPA 是一份充满威胁感的合法协议,以至于很多只是想自由参与其中的成员觉得荒谬而无法签字。值得一提的是,正因如此,Apache软件基金会(Apache Software Foundation )和其他一些高级成员在几年前纷纷退出,详见 interview with Patrick Curran on InfoQ

目前JCP有3个层次的成员:

  1. 自由参与者: 可能去修复一些少重现的Bug;
  2. 有选举权,但是不想参与主持规范的;
  3. 规范主持者。

相对应的,JSPA将被修改成三个文档:

  1. 面向自由在线贡献者的有关条款;
  2. 面向想拥有选举权、有权利为JSR专家组(EG)服务的简单会员协议;
  3. 面向规范者主持者的完整协议。

令人担心的是:假设JSAP协议条款太宽泛,一些大公司可能因为担心在知识产权上失去控制而不想参加;但是假设太严格。他们又会觉得受”威胁“。因此现在必须平衡好这个矛盾。

假设JSPA修订成功的被大众认可,我们将在InfoQ开辟专栏论述。下次JCP执行委员会会议将在2012年9月11-12日在捷克共和国布拉格采用面对面的方式进行。

原文链接:Inside the Java Community Process