雅科科+;gradle taskdef找不到类org.jacoco.ant.InstrumentTask所需的类

雅科科+;gradle taskdef找不到类org.jacoco.ant.InstrumentTask所需的类,gradle,jacoco,Gradle,Jacoco,我想让jacoco和gradle一起工作。看看这个论坛,似乎有些人已经成功地做到了这一点。但当我尝试时,我得到了一个奇怪的例外 我所做的: 1.下载gradle 2.2.1和配置的环境变量等 2.从下载的jacoco 0.7.1 3.2增加: apply plugin: 'jacoco' 及 在建造中,格雷德尔 4.运行渐变构建 5.我收到一个错误,说找不到jacoco代理jar,等等。错误消息显示它试图搜索C:\Program files(x86)\Android\Android sdk\

我想让jacoco和gradle一起工作。看看这个论坛,似乎有些人已经成功地做到了这一点。但当我尝试时,我得到了一个奇怪的例外

我所做的:

1.下载gradle 2.2.1和配置的环境变量等

2.从下载的jacoco 0.7.1

3.2增加:

 apply plugin: 'jacoco'

在建造中,格雷德尔

4.运行渐变构建

5.我收到一个错误,说找不到jacoco代理jar,等等。错误消息显示它试图搜索C:\Program files(x86)\Android\Android sdk\extras\Android\m2repository下的文件。。。等等

6.我手动解压缩了JacocoJAR文件,并将它们放在上面提到的错误消息和错误消息消失的地方

7.然后我运行gradle build。运行内置instrumentDebug任务时,我遇到以下新错误:

Caused by: : taskdef A class needed by class org.jacoco.ant.InstrumentTask cannot be found: org/jacoco/core/runtime/IExecutionDataAccessorGenerator using the classloader AntClassLoader[C:\Program Files (x86)\Android\android-sdk\extras\android\m2repository\org\jacoco\org.jacoco.ant\0.7.1.201405082137\org.jacoco.ant-0.7.1.201405082137.jar]
    at org.apache.tools.ant.taskdefs.Definer.addDefinition(Definer.java:612)

    at org.apache.tools.ant.taskdefs.Definer.execute(Definer.java:237)
    at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:292)
    at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
    at org.gradle.api.internal.project.ant.BasicAntBuilder.nodeCompleted(BasicAntBuilder.java:77)
    at org.gradle.api.internal.project.ant.BasicAntBuilder.doInvokeMethod(BasicAntBuilder.java:92)
    at com.android.build.gradle.internal.coverage.JacocoInstrumentTask.instrument(JacocoInstrumentask.groovy:51)
    at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:63)
    at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.doExecute(AnnotationProcessingTaskFactory.java:218)
    at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:211)


Caused by: java.lang.ClassNotFoundException: 

    at org.jacoco.core.runtime.IExecutionDataAccessorGenerator
    at org.apache.tools.ant.AntClassLoader.findClassInComponents(AntClassLoader.java:1366)
    at org.apache.tools.ant.AntClassLoader.findClass(AntClassLoader.java:1315)
    at org.apache.tools.ant.AntClassLoader.loadClass(AntClassLoader.java:1068)...
当我使用process monitor(我的开发机器是Win 7)时,我看到没有访问org.jacoco.core-0.7.1.201405082137.jar的权限,org.jacoco.ant.InstrumentTask类驻留在其中。因此我认为gradle没有正确地将文件路径传递给org.apache.tools.ant.AntClassLoader

我尝试过以下方法,但没有一种有效:

  • 将所有JACOCOJAR文件添加到CLASSPATH环境变量
  • 将jacocojar文件添加到antlibs、gradlelibs、gradlelibs/plugins文件夹中
  • 请看Gradle2.2.1的源代码。此时此刻不知所措
  • 有人知道如何解决这个问题吗

    提前谢谢

    编辑:

    主要目的是:

    1。让jacoco构建一个插入指令的apk文件

    2。手动测试apk文件(非自动测试)

    3。让jacoco生成覆盖率报告

    更新: 我刚刚发现,在执行InstrumentDebug任务时,gradle使用以下命令启动一个新进程:

    “C:\Program Files\Java\jdk1.8.0\U 25\bin\Java.exe”-XX:MaxPermSize=512m-Xmx2048m-Dfile.encoding=UTF-8-Duser.country=CN-Duser.language=zh-Duser.variant-cp D:\gradle-2.2.1\gradle-2.2.1\lib\gradle-launcher-2.2.1.jar org.gradle.launcher.dauncher.daemon.bootstrap.gradle.GradleDaemon 2.2.2.2.1 D:\gradle-2.2.2.2.1\gradle-2.2.2.2.1\daemon 120000 744501ac-32c1-4930-82bd-59E0A9E292D-518M-xm048M-Dfile.encoding=UTF-8-Duser.country=CN-Duser.language=zh-Duser.variant

    正如您所看到的,类路径是硬编码的,它覆盖了环境变量中定义的内容。因此,无法找到jacoco所需的核心库,从而导致此问题。我现在试图看看这个过程是从哪里开始的,以及是否有办法更改-cp选项

    更新2: 我终于发现这个过程是由gradle-launcher-2.2.1.jar启动的。请参阅下面的代码。我现在尝试查看是否可以更改DefaultModuleRegistry并使registry.getGradleHome()==null在此期间,任何成功使用jacoco+gradle的人都可以告诉我您使用的是哪个版本的gradle吗?

    public DaemonStartupInfo startDaemon()
    {
    DefaultModuleRegistry registry = new DefaultModuleRegistry();
    Set<File> bootstrapClasspath = new LinkedHashSet();
    bootstrapClasspath.addAll(registry.getModule("gradle-launcher").getImplementationClasspath().getAsFiles());
    if (registry.getGradleHome() == null) 
    {
      bootstrapClasspath.addAll(registry.getFullClasspath());
    }
    if (bootstrapClasspath.isEmpty()) {
      throw new IllegalStateException("Unable to construct a bootstrap classpath when starting the daemon");
    }    
    new JvmVersionValidator().validate(this.daemonParameters);
    List<String> daemonArgs = new ArrayList();
    daemonArgs.add(this.daemonParameters.getEffectiveJavaExecutable());
    List<String> daemonOpts = this.daemonParameters.getEffectiveJvmArgs();
    LOGGER.debug("Using daemon opts: {}", daemonOpts);
    daemonArgs.addAll(daemonOpts);
    daemonArgs.add("-cp");
    daemonArgs.add(CollectionUtils.join(File.pathSeparator, bootstrapClasspath));
    daemonArgs.add(GradleDaemon.class.getName());
    daemonArgs.add(GradleVersion.current().getVersion());
    daemonArgs.add(this.daemonDir.getBaseDir().getAbsolutePath());
    daemonArgs.add(String.valueOf(this.daemonParameters.getIdleTimeout()));
    daemonArgs.add(this.daemonParameters.getUid());
    
    ...
    }
    
    public守护进程startupinfo startDaemon()
    {
    DefaultModuleRegistry注册表=新建DefaultModuleRegistry();
    Set bootstrapClasspath=new LinkedHashSet();
    bootstrapClasspath.addAll(registry.getModule(“gradle启动器”).getImplementationClasspath().getAsFiles());
    if(registry.getGradleHome()==null)
    {
    bootstrapClasspath.addAll(registry.getFullClasspath());
    }
    if(bootstrapClasspath.isEmpty()){
    抛出新的IllegalStateException(“启动守护进程时无法构造引导类路径”);
    }    
    新的JvmVersionValidator().validate(this.daemonParameters);
    List daemonArgs=new ArrayList();
    add(this.daemonParameters.getEffectiveJavaExecutable());
    List daemonOpts=this.daemonParameters.getEffectiveJvmArgs();
    debug(“使用守护进程选项:{}”,daemonOpts);
    daemonArgs.addAll(daemonOpts);
    daemonArgs.add(“-cp”);
    daemonArgs.add(CollectionUtils.join(File.pathselector,bootstrapClasspath));
    daemonArgs.add(GradleDaemon.class.getName());
    daemonArgs.add(GradleVersion.current().getVersion());
    add(this.daemonDir.getBaseDir().getAbsolutePath());
    add(String.valueOf(this.daemonParameters.getIdleTimeout());
    add(this.daemonParameters.getUid());
    ...
    }
    
    看看这是否有帮助。 我没有使用Gradle 2.2.1,但这是我的全局Gradle文件(即$Gradle_HOME/init.d级别文件)中的文件。文件名可以是扩展名为.gradle的任何内容

    allprojects {
       apply plugin: 'java'
       apply plugin: 'pmd'
       apply plugin: 'findbugs'
       apply plugin: 'checkstyle'
       apply plugin: 'jacoco'
    
       //NOTE1: The following soureSet section is NOT required, if your folder structure follows what Gradle says where your main source should reside, where test (Unit tests) should reside, and where other like integrationTest (integration tests code reside). If your project structure doesn't follow the Gradle defined structure, then you can define that as my source code is not under src/main/java but is under src/java. The use of "sourceSet" section in this global file is only helping to use some conventional values in this global level file for ex: see integrationTest task and jacocoTestReport task below (you can't use those values if sourceSet is NOT defined in this file and if your project doesn't following the Gradle defined structure).
    
      //NOTE2: Here in the global level Gradle file, I'm using values for sources for main, test, integrationTest etc as "dont_change_me" as I don't know what all projects (which will use this Gradle's global level file), will have what source code structure. The main / actual values of the sources for main, test and integrationTest task MUST be defined in the PROJECT's build.gradle file in sourceSets { main { java { srcDir 'src/java' } } } way.
    
    
       sourceSets {
          main {
             java {
                srcDir 'dont_change_me'
             }
             resources {
                srcDir 'dont_change_me'
             }
          }
          test {
             java {
                srcDir 'dont_change_me'
             }
             resources {
                srcDir 'dont_change_me'
             }
          }
          integrationTest {
             java {
                srcDir 'dont_change_me'
             }
             resources {
                srcDir 'dont_change_me'
             }
          }
          acceptanceTest {
             java {
                srcDir 'dont_change_me'
             }
             resources {
                srcDir 'dont_change_me'
             }
          }
    
       }
    
       //...more code here
       //...more code here
    
       // The following is necessary to get code coverage info out. Compile with debug mode.
       tasks.withType(Compile) {
         options.debug = true
         options.compilerArgs = ["-g"]
       }
    
       jacoco {
            //toolVersion = "0.6.2.201302030002"
            //toolVersion = "0.7.0.201403182114"
            //toolVersion = "0.7.1.201404171759"
    
            //This is latest than above, you may find later versions in online Maven repository.
            toolVersion = "0.7.2.201409121644"
    
            //OK I don't need the following folder to be created as I'll define my own.
            // reportsDir = file("$buildDir/customJacocoReportDir")
    
       }
    
       //The following section is for UNIT tests (as build task in Gradle calls test task for free)
       test {
         maxParallelForks = 5
         forkEvery = 50
         ignoreFailures = true
    
         // I want my reports (html) files to be created in a user defined folder UT(Unit test in build/reports/UT folder) and xml files (in user defined folder UT folder) under build/test-results/UT folder.
         testReportDir = file("$buildDir/reports/tests/UT")
         testResultsDir = file("$buildDir/test-results/UT")
    
         //Following jacoco session will RUN in GRADLE's JVM session (during build / test time). This is different JVM than what many think of a runtime/Tomcat JVM session where we run a .war/.ear/etc file of an app to run that app and if you want to get code coverage of your main source code using non-unit tests from a Tomcat JVM, then see next task (integrationTest) as the following jacoco section in this "test" task is just for UNIT tests running in Gradle JVM session on a machine.
         jacoco {
            //NOTE: The following vars works ONLY with Gradle <= 1.6 version
    
            // Create jacoco .exec file for Unit test in a user defined location
            destPath = file("$buildDir/jacoco/UT/jacocoUT.exec")
            //The following line is not that usesful acc. to my experience so commented it.
            //classDumpPath = file("$buildDir/jacoco/UT/classpathdumps")
    
    
    
            //NOTE: Following vars works only with versions >= 1.7 version of Gradle
            //destinationFile = file("$buildDir/jacoco/UT/jacocoUT.exec")
            //  classDumpFile = file("$buildDir/jacoco/UT/classpathdumps")
         }
       }
    
    
       task integrationTest( type: Test) {
    
         //Always run tests
         outputs.upToDateWhen { false }
    
         //Ignore the failures if any during tests and don't mark the Gradle task as failed.
         //You can comment this line if you want your gradle task to fail as soon as it finds any failing tests.
         ignoreFailures = true
    
         //This is telling Gradle that where it'll find class files from integration tests source code
         testClassesDir = sourceSets.integrationTest.output.classesDir
         //What path to use in classpath for integration tests
         classpath = sourceSets.integrationTest.runtimeClasspath
    
         //My custom location where I want my html reports files and xml result times of integration tests
         testReportDir = file("$buildDir/reports/tests/IT")
         testResultsDir = file("$buildDir/test-results/IT")
    
         //Jacoco section in IT tests is NOT required here. Why as it'll never generage a coverage report this way as this way of using jacoco section in integrationTest task is telling Gradle to use jacoco in Gradle JVM and for getting code coverage you have to run jacoco/jacocoagent.jar in Target JVM (which is Tomcat or similar) by introducing jacocoagent.jar and other parameters for jacoco to Tomcat using one of Tomcat's -Dxxx option (see Jacoco help on how to do this). As the following is not required, I'm commenting the following jacoco code(otherwise if used, it'll always give you 0% coverage).
            //jacoco {
               //This works with 1.6
               //  destPath = file("$buildDir/jacoco/IT/jacocoIT.exec")
               //  classDumpPath = file("$buildDir/jacoco/IT/classpathdumps")
    
               //Following works only with versions >= 1.7 version of Gradle
               //destinationFile = file("$buildDir/jacoco/IT/jacocoIT.exec")
               //  classDumpFile = file("$buildDir/jacoco/IT/classpathdumps")
            //}
      }
    
    
      jacocoTestReport {
          group = "Reporting"
          description = "Generate Jacoco coverage reports after running tests."
          ignoreFailures = true
    
          //Use any .exec file found before generating coverage report i.e. it'll give you combined coverage report if you have both jacocoUT.exec and jacocoIT.exec or other .exec files in build/jacoco/xx folders.
          executionData = fileTree(dir: 'build/jacoco', include: '**/*.exec')
    
          //executionData = files('build/jacoco/UT/jacocoUT.exec', 'build/jacoco/IT/jacocoIT.exec')
          //executionData = files(['build/jacoco/UT/jacocoUT.exec', 'build/jacoco/IT/jacocoIT.exec'])
    
          reports {
                 xml{
                     enabled true
                     //Following value is a file
                     destination "${buildDir}/reports/jacoco/xml/jacoco.xml"
                 }
                 csv.enabled false
                 html{
                     enabled true
                     //Following value is a folder
                     destination "${buildDir}/reports/jacoco/html"
                 }
          }
    
          //The following is an example of using Gradle conventional way of saying where is my main source code directory
          //sourceDirectories = files(sourceSets.main.allJava.srcDirs)
    
          sourceDirectories = files(['src/java', 'src/groovy'])
          classDirectories =  files('build/classes/main')
      }
    
    }
    
    在我使用的startTomcat.sh脚本中,您会注意到我正在使用上述变量并将其传递给Tomcat的JVM,因为这是运行我的项目的main.war/.ear文件的JVM,该文件包含主要的源代码类文件,我希望使用集成/验收/其他非单元类型测试对其进行代码破解数据:

    ## Tomcat command - JDK 1.6/Tomcat 6.0
    TOMCAT_CMD="$JAVA_HOME/bin/java $TOMCAT_JVM_ARGS \
    $OPTIT_JVM_ARGS \
    
    $JPROF_JVM_ARGS \
    $PROJ_EXTRA_JVM_OPTS \
    org.apache.catalina.startup.Bootstrap $TOMCAT_CFG_FILE_ARGS start"
    

    上述变量需要存在于Tomcat启动脚本中,即当Tomcat启动时,它应该在其JVM会话中获取上述变量。完成后,您必须运行“gradle integrationTest”,然后停止Tomcat会话(只有这样它才会将代码覆盖率数据刷新到jacocoIT.exec文件),如果您运行“gradle jacocoTestReport”,它将阅读jacocoIT.exec文件和genreate jacoco代码覆盖率报告,了解集成/验收/Selenium测试试图覆盖的主要源代码。

    您是否遵循了Gradle指南(第34章):。我还没有试过Gradle2.2.1,但我想问你的问题是,你是在尝试使用“单元测试”还是“集成/验收/Selenium/etc GUI测试”来获得主要源代码的代码覆盖率?如果它使用的是您的单元测试,那么Gradle将在您运行“Gradle clean build”时免费这么做。如果您希望使用非单元测试覆盖主要源代码,那么您必须将jacocoagent附加到目标JVM(例如:在目标服务器的Tomcat JVM中运行.war of a app)。此外,请粘贴build.gradle。@ArunSangal,感谢您的回复。
    export PROJ_EXTRA_JVM_OPTS="-javaagent:tomcat/jacocoagent.jar=destfile=build/jacoco/${testType}/jacoco${testType}.exec,append=false"
    
    ## Tomcat command - JDK 1.6/Tomcat 6.0
    TOMCAT_CMD="$JAVA_HOME/bin/java $TOMCAT_JVM_ARGS \
    $OPTIT_JVM_ARGS \
    
    $JPROF_JVM_ARGS \
    $PROJ_EXTRA_JVM_OPTS \
    org.apache.catalina.startup.Bootstrap $TOMCAT_CFG_FILE_ARGS start"