乐者为王

Do one thing, and do it well.

Ant系列之用EMMA测量测试覆盖率的问题

EMMA是一个coverage工具,有on-the-fly和offline两种使用方式,在Ant里通常采用offline方式。

到sourceforge下载了2.0版本的EMMA下来,由于将EMMA的生成文件做了重定向,因此遇到了些问题,比如出现以下错误:

1
nothing to do: no runtime coverage data found in any of the data files

查找EMMA的FAQ 3.7节,只是告诉你可能少了metadata和runtime coverate date(对Ant用户来说一般是少了runtime coveraget date,它的后缀名默认是ec)。

由FAQ 3.15节可以知道runtime coverage data文件默认是生成在user.dir目录下的(即build.xml中的basedir目录下),而由instr指令生成的metadata文件(后缀名默认为em)则已经被重定向到另外的目录(用来生成coverage report的地方),所以必须重新设置coverage.out.file的值,用来重定向生成的runtime coverage data。因为runtime coverage data是在junit任务执行时产生的,所以我们可以在junit任务中添加一行代码:

1
<sysproperty key="emma.coverage.out.file" value="${coverage.dir}/coverage.emma" />

注意:

  1. metadata和runtime文件的后缀名最好设置相同;
  2. 一定要将junit任务的fork属性设置为true,这是因为EMMA 2.0的runtime coverage data是在JVM退出后生成的;
  3. instrumented classes必须是第一个被JVM执行的,所以instrumented classes目录必须处在junit任务的classpath的第一行,具体原因不明,如果谁知道还请告知下。

其实EMMA附带的examples目录下的build-offline.xml里已经说明的很详细了,只不过下载后没有仔细看,才遇到了一些问题。下面是build.xml的部分代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<path id="classpath">
  <pathelement location="${instrumentedclasses}" />
  <pathelement location="${classes}" />
  <pathelement location="${testclasses}" />
  <fileset dir="${lib}" includes="**/*.jar" />
</path>

<target name="compile" depends="prepare">
  <javac srcdir="${src}" destdir="${classes}" debug="on">
    <classpath refid="classpath" />
  </javac>
  <javac srcdir="${test}" destdir="${testclasses}" debug="on">
    <classpath refid="classpath" />
  </javac>
</target>

<target name="coverage.instrument" depends="compile">
  <emma enabled="yes">
    <instr instrpath="${classes}" destdir="${instrumentedclasses}"
        metadatafile="{coveragereports}/metadata.emma" merge="true">
    </instr>
  </emma>
</target>

<target name="junit" depends="coverage.instrument">
  <junit printsummary="yes" haltonfailure="no" fork="true">
    <sysproperty key="emma.coverage.out.file" value="${coveragereports}/coverage.emma" />
    <classpath refid="classpath" />

    <formatter type="xml" />

    <batchtest fork="yes" todir="${junitreports}">
      <fileset dir="${test}">
        <include name="**/*Test*.java" />
      </fileset>
    </batchtest>
  </junit>
</target>

<target name="coverage.report" depends="test">
  <emma enabled="yes">
    <report sourcepath="${src}">
      <fileset dir="${coveragereports}">
        <include name="*.emma" />
      </fileset>

      <html outfile="${coveragereports}/coverage.html" depth="method" />
    </report>
  </emma>
</target>

Comments