首页 文章

在已经检测过的文件上从gradle运行jacoco

提问于
浏览
0

我正在为java项目尝试jacoco离线检测 .

我创建了一个hello world gradle java项目,并使用jacoco对其生成的类文件进行了检测 . 当我尝试对这些检测文件运行测试时 . 我收到了以下错误 .

CUTest.java上的java.lang.ClassCastException: - 1

反编译的测试.class文件是

import org.junit.Test;

public class CUTest
{
  public CUTest()
  {
    arrayOfBoolean[0] = true;
  }

  @Test
  public void test()
  {
    boolean[] arrayOfBoolean = $jacocoInit();CUT localCUT1 = new CUT();arrayOfBoolean[1] = true;
    CUT c;
    c.meth();
    arrayOfBoolean[2] = true;
  }
}

检测源.class文件是

import java.io.PrintStream;

public class CUT
{
  public CUT()
  {
    arrayOfBoolean[0] = true;
  }

  public void meth()
  {
    boolean[] arrayOfBoolean = $jacocoInit();System.out.println("hello world");
    arrayOfBoolean[1] = true;
  }
}

jacoco agent jar存在于classpath中 . 我在build.gradle中添加了一个测试编译依赖项 .

这是源文件(不是反编译的类文件)

public class CUT {

    public void meth(){
        System.out.println("hello world");
    }

}

测试来源

import static org.junit.Assert.*;

import org.junit.Test;

public class CUTest {

    @Test
    public void test() {
        CUT c = new CUT();
        c.meth();
    }

}

我使用jacoco instrumentation api来编译这些类后生成的仪器类文件 . 我想从这些.class文件生成jacoco报告(已经过检测) .

以下是hello world和instrumentation的项目https://github.com/arpitgautam/jacoco-rat https://github.com/arpitgautam/jacoco

1 回答

  • 0

    README.md 中描述的提交 f4786df19a930726ebada97461d2a54ad463a4ec 中使用https://github.com/arpitgautam/jacoco-rat中的示例:

    gradle build
    从build.gradle取消注释gradle.taskGraph.beforeTask

    但在期间

    在jacoco-rat \ build \ classes中获取文件,并使用jacoco instrumentation api替换由检测的类替换类 .

    在需要提交 5e7ac40627eb4e2f0882ce143f5840ee9774af57 时使用https://github.com/arpitgautam/jacoco

    将ROOT更改为classes文件夹的绝对路径

    这是我的情况

    public static final String ROOT = "/tmp/jacoco-rat/build/classes/";
    

    拿到

    Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 32
        at java.lang.String.substring(String.java:1963)
        at com.exp.tools.JavaClassVisitor.createNewFolderName(JavaClassVisitor.java:69)
    

    因此,使用JaCoCo command-line interface(将在下一版本中提供)来仪器类:

    java -jar jacococli.jar instrument build/classes --dest build/instrumented
    

    并取代原件:

    rm -r build/classes
    mv build/instrumented build/classes
    

    然后再次执行Gradle为 gradle test --info 并看到该异常不是 java.lang.ClassCastException ,但是

    java.lang.NoClassDefFoundError: org/jacoco/agent/rt/internal_8ff85ea/Offline
        at com.exp.tools.CUTest.$jacocoInit(CUTest.java)
        at com.exp.tools.CUTest.<init>(CUTest.java)
    
        Caused by:
        java.lang.ClassNotFoundException: org.jacoco.agent.rt.internal_8ff85ea.Offline
            at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
            at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
            at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335)
            at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
            ... 2 more
    

    引用JaCoCo FAQ

    为什么我收到错误“ClassNotFoundException:org.jacoco.agent [...] Offline”?如果使用脱机检测,则检测的类将直接依赖于JaCoCo运行时 . 因此,同一JaCoCo版本的jacocoagent.jar必须位于类路径上,并且可以通过检测类访问 .

    根据http://www.jacoco.org/jacoco/trunk/doc/repo.html

    组ID工件ID描述
    org.jacoco org.jacoco.agent用于获取代理的本地副本的API

    Maven资源库中的工件 org.jacoco:org.jacoco.agent 不是一个真正的代理,而是一个获取它的API . 实际代理有分类器 runtime ,即代替

    testCompile group: 'org.jacoco', name: 'org.jacoco.agent', version: '0.7.9'
    

    你绝对应该使用

    testCompile group: 'org.jacoco', name: 'org.jacoco.agent', classifier: 'runtime', version: '0.7.9'
    

    并修复https://github.com/arpitgautam/jacoco中的问题,其中你可能错误地使用导致 java.lang.ClassCastException 的JaCoCo API,或者使用已经开发的标准JaCoCo工具来执行仪器,例如上面提到的命令行界面,Ant TasksMaven Pluginetc .

相关问题