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

Posted by dohkoos on January 16th, 2006 (1,190 views)

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

到sf下载了2.0版本的EMMA下来,由于将EMMA的生成文件做了重定向,因此遇
到了一些问题,如:
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 task中添加一行代码:
<sysproperty key="emma.coverage.out.file" value="${coverage.dir}/coverage.emma" />

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

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

// snippet for build.xml
<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="test" 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>

Related Posts

People who read this, also read...

Ant系列之用JDepend生成package依赖性度量的问题

Posted by dohkoos on December 29th, 2005 (566 views)

首先获取jdepend的最新jar文件,当前最新版本是2.9。将jdepend-2.9.jar添加
到ANT_HOME/lib目录。

在build.xml中添加:
<target name="jdepend" description="Generate dependency metrics for each package">
    <jdepend format="xml" outputfile="${jdepend.dir}/jdepend-report.xml">
        <classpath>
            <pathelement path="classes" />
        </classpath>
    </jdepend>
</target>

运行任务后出现如下的错误:
BUILD FAILED
C:examplebuild.xml:59: Missing classespath required argument
    at org.apache.tools.ant.taskdefs.optional.jdepend.JDependTask.execute(JDependTask.java:397)
    at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:275)
    at org.apache.tools.ant.Task.perform(Task.java:364)
    at org.apache.tools.ant.Target.execute(Target.java:341)
    at org.apache.tools.ant.Target.performTasks(Target.java:369)
    at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1216)
    at org.apache.tools.ant.Project.executeTarget(Project.java:1185)
    at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:40)
    at org.eclipse.ant.internal.ui.antsupport.EclipseDefaultExecutor.executeTargets(EclipseDefaultExecutor.java:32)
    at org.apache.tools.ant.Project.executeTargets(Project.java:1068)
    at org.eclipse.ant.internal.ui.antsupport.InternalAntRunner.run(InternalAntRunner.java:423)
    at org.eclipse.ant.internal.ui.antsupport.InternalAntRunner.main(InternalAntRunner.java:137)

查看JDependTask.java文件的397行
if (getSourcespath() == null && getClassespath() == null) {
    throw new BuildException("Missing classespath required argument");
} else if (getClassespath() == null) {
    String msg = "sourcespath is deprecated in JDepend >= 2.5 "
            + "- please convert to classespath";
    log(msg);
}

发现是getClassespath() == null了,跳到221行
public Path getClassespath() {
    return classesPath;
}

不是写了classpath了吗?怎么classesPath会等于null呢?结果发现在247行有
public void setClasspath(Path classpath) {
    if (compileClasspath == null) {
        compileClasspath = classpath;
    } else {
        compileClasspath.append(classpath);
    }
}

原来是在build.xml中把classespath错写成classpath了,那样当然有问题啦。改过来,再运行就可以了。

Related Posts

People who read this, also read...

Ant系列之用Checkstyle检查代码规范的问题

Posted by dohkoos on December 16th, 2005 (1,113 views)

在ant的build.xml文件中添加CheckStyle任务的步骤如下:

1. 将checkstyle-all-4.1.jar拷贝到项目的lib目录;
2. 建立配置文件;
3. 声明checkstyle任务:
<taskdef resource="checkstyletask.properties" classpath="${lib.dir}/checkstyle-all-4.1.jar" />
4. 建立checkstyle任务:
<target name="checkstyle" description="Generates a report of code convention violations.">
    <checkstyle config="${docs.dir}/checkstyle_checks.xml" failOnViolation="false">
        <fileset dir="${src.dir}" includes="**/*.java" />
        <formatter type="xml" toFile="${checkstyle.dir}/checkstyle_report.xml" />
    </checkstyle>
    <xslt basedir="${checkstyle.dir}" destdir="${checkstyle.dir}/html" extension=".html"
            style="${docs.dir}/checkstyle-frames.xsl">
        <param name="output.dir" expression="${checkstyle.dir}/html" />
    </xslt>
</target>
其中output.dir是checkstyle-frames.xsl中的参数:<xsl:param name="output.dir" />

在运行checkstyle任务时可能会出现异常javax.xml.transform.TransformerException: java.lang.RuntimeException: Unrecognized XSLTC extension 'org.apache.xalan.xslt.extensions.Redirect:write',
可以将checkstyle-frames.xsl中的xmlns:redirect="org.apache.xalan.xslt.extensions.Redirect改成xmlns:redirect="http://xml.apache.org/xalan/redirect"。

出现Got an exception - java.lang.RuntimeException: Unable to get class information for XxxException.
异常时可以修改对于Throws的的限制:允许Throws Unchecked Exception以及Throws Subclass Of Another Declared Exception。
<module name="RedundantThrows">
    <property name="allowUnchecked" value="true" />
    <property name="allowSubclasses" value="true" />
</module>

Related Posts

People who read this, also read...

Eclipse环境中Junit结合Ant进行自动测试的问题(2)

Posted by dohkoos on February 23rd, 2005 (750 views)

Environment:eclipse-3.0.3 + ant-1.6.2 + junit-3.8.1

// build.xml
<target name="test">
<junit>
    <formatter type="xml" />
    <batchtest todir="${report.dir}">
        <fileset dir="${classes.dir}" includes="**/*Test.class" />
    </batchtest>
</junit>
</target>

执行脚本的时候出现了以下的错误:

java.lang.ClassNotFoundException: example.AdditionTest
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClassInternal(Unknown Source)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Unknown Source)

将<fileset dir="${classes.dir}" includes="**/*Test.class" /> 改成<...includes="**/*Test.*" />
或者<...includes="**/*Test" /> 都不行。只有改成<...includes="**/*Test.java" />才可以,可
是改成<...includes="**/*Test.java" /> 后测试无任何效果,肯定通过。用google 搜也搜
不到答案,到ant 网站http://ant.apache.org/faq.html#delegating-classloader上去查找,才
找到原因。

在上述情况中,Ant 不会去加载example.AdditionTest。而只是加载了junit库,junit
再去加载example.AdditionTest,由于java 加载采用的是delegation 模式,而且junit 和
example.AdditionTest 不在同一个空间,所以junit 会调用parent 的classLoader 来加载
库,结果就出现上面的ClassNotFoundException 提示信息啦。

因此,只要载<junit></junit> 间加入classpath 指出要加载库的路径就可以了,修改
后的build.xml 文件如下:
// build.xml
<target name="test">
<junit>
    <classpath>
            <pathelement location="${classes.dir}" />
    </classpath>
    <formatter type="xml" />
    <batchtest todir="${report.dir}">
        <fileset dir="${classes.dir}" includes="**/*Test.class" />
    </batchtest>
</junit>
</target>

Related Posts

People who read this, also read...

Eclipse环境中Junit结合Ant进行自动测试的问题(1)

Posted by dohkoos on February 6th, 2005 (702 views)

Eclipse 3.0.3
Ant 1.6.2
Junit 3.8.1

build.xml

<target name="test">
    <junit>
        ...
    </junit>
</target>

在执行时出现了以下问题:

BUILD FAILED: C:eclipse-3.0.3workspaceDailyBuildbuild.xml:44: Could not create task or type of type: junit.

Ant could not find the task or a class this task relies upon.

This is common and has a number of causes; the usual
solutions are to read the manual pages then download and
install needed JAR files, or fix the build file:
 - You have misspelt 'junit'.
   Fix: check your spelling.
 - The task needs an external JAR file to execute
     and this is not found at the right place in the classpath.
   Fix: check the documentation for dependencies.
   Fix: declare the task.
 - The task is an Ant optional task and the JAR file and/or libraries
     implementing the functionality were not found at the time you
     yourself built your installation of Ant from the Ant sources.
   Fix: Look in the ANT_HOME/lib for the 'ant-' JAR corresponding to the
     task and make sure it contains more than merely a META-INF/MANIFEST.MF.
     If all it contains is the manifest, then rebuild Ant with the needed
     libraries present in ${ant.home}/lib/optional/ , or alternatively,
     download a pre-built release version from apache.org
 - The build file was written for a later version of Ant
   Fix: upgrade to at least the latest release version of Ant
 - The task is not an Ant core or optional task
     and needs to be declared using <taskdef>.
 - You are attempting to use a task defined using
    <presetdef> or <macrodef> but have spelt wrong or not
   defined it at the point of use

Remember that for JAR files to be visible to Ant tasks implemented
in ANT_HOME/lib, the files must be in the same directory or on the
classpath

Please neither file bug reports on this problem, nor email the
Ant mailing lists, until all of these causes have been explored,
as this is not an Ant bug.

产生上面的错误原因是Ant在执行Junit程序时没有找到junit.jar这个文件,将junit.jar文件copy到ANT_HOME/lib目录下,再次执行ant test任务,waiting...

这下该OK了吧^_^

有没有搞错,还产生同样的错误!到窗口下试试。进入命令行窗口,输入ant test,再次等待ing

Buildfile: build.xml

test:

BUILD SUCCESSFUL
Total time: 1 second

怎么会这样的???命令行窗口下可以,Eclipse下就不行了。

到Preferences -> Ant -> Runtime -> Classpath下设置一下junit.jar的路径,再次执行ant test任务,终于在console中看到了

test:

BUILD SUCCESSFUL
Total time: 4 seconds

Related Posts

People who read this, also read...