2014-12-24 2 views
1

jacoco + gradle 작업을 함께 시도하고 있습니다. 이 포럼을 보면 일부 사람들이 성공적으로이를 수행 한 것으로 보입니다. 그러나 내가 시도했을 때 나는 이상한 예외를 얻었다.jacoco + gradle taskdef org.jacoco.ant.InstrumentTask 클래스에서 필요한 클래스를 찾을 수 없습니다.

내가 무슨 짓을 : http://www.eclemma.org/jacoco/

3.added에서

1.Downloaded Gradle을 2.2.1 및 구성 ENV 변수 등

2.Downloaded jacoco 0.7.1 :

apply plugin: 'jacoco' 

buildTypes { 
     debug 
{ 
     testCoverageEnabled true 
... 
,536,913,632 build.gradle 10

4.run Gradle을 찾을 수 없습니다

5.I가 jacoco 에이전트 항아리를 말하는 오류가 발생했습니다 구축 등의 오류 메시지는 C에서 파일을 검색하려고했다 : \ 프로그램 파일 (x86) \ Android \ android-sdk \ extras \ android \ m2repository ... 등

6. 수동으로 jacoco jar 파일의 압축을 풀고 오류 메시지와 오류 메시지가 표시된 위치에 넣습니다. 사라졌다.

7. 그럼 나는 gradle 빌드를 실행했습니다. 실행할 때 나는 다음과 같은 새로운 오류가 발생했습니다 내장 instrumentDebug 작업 : 나는 (내 dev에 기계 승 7) 프로세스 모니터를 사용하는 경우, 내가 org.jacoco.core-0.7에 대한 액세스 권한이 없었다 보았다

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)... 

.1.201405082137.jar, org.jacoco.ant.InstrumentTask 클래스가 상주합니다. 따라서 그라디언트가 org.apache.tools.ant.AntClassLoader 파일 경로를 올바르게 전달하지 않았다고 생각합니다.

내가 방법을 아래에 시도했지만 그들 중 누구도 일하지 :

  1. 는 CLASSPATH 환경 변수에 모든 jacoco jar 파일을 추가합니다.
  2. jacoco jar 파일을 ant libs, gradle libs, gradle libs/plugins 폴더에 추가하십시오.
  3. gradle 2.2.1의 소스 코드를 살펴보십시오. 이 순간에 우둔 ...

누구든지이 문제를 해결하는 방법을 알고 있습니까?

미리 감사드립니다.

편집 :

주요 목적이다 :

2. 수동으로 APK 파일을 테스트 계장 APK 파일을 구축 jacoco

1하자 (하지 자동 테스트)

3.jacoco 취재 보고서 생성하자

업데이트 : InstrumentDebug 작업 실행의 Gradle을 명령 아래에 새로운 프로세스를 시작할 때 난 그냥 발견

"C : \ 프로그램 파일 \ 자바 \ jdk1.8.0_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.daemon.bootstrap.GradleDaemon 2.2.1 D : \ gradle-2.2.1 \ gradle-2.2.1 \ daemon 120000 744501ac- 32c1-4930-82bd-59e0a9e2b92d -XX : MaxPermSize = 512m -Xmx2048m -Dfile.encoding = UTF-8 -Duser.country = CN -Duser.language = zh -Duser.variant

클래스 경로가 하드 코딩되어있어 환경 변수에 정의 된 것을 덮어 씁니다. 따라서 jacoco의 필수 코어 lib를 찾을 수 없으므로이 문제가 발생합니다. 이제이 프로세스가 시작된 곳과 -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()); 

... 
} 
+0

지면 가이드 (34 장)를 따라 보았습니까 : http://www.gradle.org/docs/current/userguide/jacoco_plugin.html. 나는 Gradle 2.2.1을 사용하지 않았지만, "unit tests"를 사용하거나 "integration/acceptance/Selenium/etc GUI 테스트"를 사용하여 주요 소스 코드의 코드 커버리지를 얻으려고합니까? UNIT 테스트를 사용하는 경우 Gradle은 "gradle clean build"를 실행할 때 무료로 수행합니다. 비 - 유닛 테스트를 사용하여 주요 소스 코드의 코드 범위를 원할 경우 jacocoagent를 대상 JVM에 첨부해야합니다 (예 : 대상 서버의 Tomcat JVM에서 응용 프로그램의 .war가 실행되는 경우). –

+0

또한 build.gradle을 붙여 넣으십시오. –

+0

@ ArunSangal, 답장을 보내 주셔서 감사합니다. 나는 나의 목적을 업데이트했다. 나는 이제 # 1에 머물렀다. 내 build.gradle에는 특별한 것이 없습니다. 방금 언급 한 3 단계를 추가했습니다. –

답변

1

이 정보가 도움이되는지 확인하십시오. Gradle 2.2.1을 사용하고 있지는 않지만 내 글로벌 Gradle 파일 (예 : $ GRADLE_HOME/init.d 수준의 파일)에 있습니다. 파일 이름은 확장자가 .gradle 인 항목 일 수 있습니다. Gradle을 그것을해야한다라고하는 것보다 프로젝트 구조와 다른 경우 경우 프로젝트의 build.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') 
    } 

} 

, 당신은 (실제 값) sourceSets 섹션을 정의합니다. 종속성을 정의합니다 (즉,이 .jar 파일을 컴파일하려면 test 또는 integrationTest가 필요하고 main 또는 test 등에서는 .jar 또는 .class가 필요합니다).

그런 다음 gradle clean build를 실행하면 .exec 파일 형식으로 build/jacoco/UT 폴더 아래에있는 UT (단위 테스트)에 대한 jacoco 코드 적용 범위 데이터가 표시됩니다. 빌드/보고서/... html 폴더 아래에 코드 커버리지 보고서를 보여줄 jacoco main index.html이 있습니다.

유닛 테스트 이외의 테스트 (예 : 통합 테스트 등)에서 코드 커버리지 보고서를 보려면 대상 JVM에 다음 매개 변수를 첨부하십시오. 나는 Tomcat을 사용하므로 testType은 IT (Integration Tests), AT (Acceptance Tests) 또는 ST (Selenium GUI tests)를 실행하는지 여부를 찾거나 알려주는 변수이다.

export PROJ_EXTRA_JVM_OPTS="-javaagent:tomcat/jacocoagent.jar=destfile=build/jacoco/${testType}/jacoco${testType}.exec,append=false" 

내가 사용 startTomcat.sh 스크립트에서, 당신은 내 프로젝트의 주요 .WAR/.ear 파일을 실행하는 JVM의 나는 위의 변수를 사용하여 Tomcat의 JVM에 전달하고있어 알 수 있습니다 이는 내가 통합/입학/기타 비-UNIT의 형식 시험 사용하여 내 코드 covreage 데이터 할에 대한 주요 소스 코드를 클래스 파일이 있습니다

## 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" 

위의 변수가 때 스크립트 즉 시작 톰캣 거기에 톰캣 할 필요를 시작하면 JVM 세션에서 위의 변수를 가져와야합니다. 이 작업이 완료되면 "gradle integrationTest"를 실행 한 다음 Tomcat 세션을 중지해야만 (코드 커버리지 데이터를 jacocoIT.exec 파일로 플러시), "gradle jacocoTestReport"를 실행하면 jacocoIT.귀하의 통합/수용/셀레늄 테스트에서 다루려고했던 주요 소스 코드에 대한 jacoco 코드 커버리지 보고서를 작성하십시오.

+0

답장을 보내 주셔서 감사합니다. 원래 목적을 업데이트했습니다. –

관련 문제