Gradle - Jacoco - JMockit - 测试悬而未决

时间:2014-04-28 21:01:51

标签: testing gradle hang jmockit jacoco

我正在使用Gradle(Gradle 1.6 -upto 1.9)来构建Java项目。尝试使用Java 1.6或1.7。

src/java  - contains Java source code
test/java - contains test java code

项目编译/构建成功。在构建期间,Junit UNIT测试也成功运行。我只有一个测试,它使用JMockit库。 请注意:这个jacoco代码在我没有需要JMockit库的测试的任何其他项目中都能正常工作。

JMockit groupid:artifactid:version is:

jmockit:jmockit:1.1

我希望启用Jacoco代码覆盖率。我到目前为止尝试过的Jacoco版本显示在下面的代码中,此代码存在于我的Gradle构建脚本中。

我在项目的build.gradle文件中添加了以下行。

apply plugin: 'jacoco'

   jacoco {
                //toolVersion = "0.6.2.201302030002"
          toolVersion = "0.7.0.201403182114"
                //toolVersion = "0.7.1.201404171759" --- trying to find how to make version this working.
                // reportsDir = file("$buildDir/customJacocoReportDir")
   }

   test {
     ignoreFailures = true
     testReportDir = file("$buildDir/reports/tests/UT")
     testResultsDir = file("$buildDir/test-results/UT")

     // Uncomment the following if you need more detailed output.  
     //testLogging.showStandardStreams = true
     //onOutput { descriptor, event ->
     //  logger.lifecycle("Test: " + descriptor + " produced standard out/err: " + event.message )
     //}

     //Following Jacoco test section is required only in Jenkins instance extra common file
     jacoco {
       //The following vars works ONLY with 1.6 of Gradle
       destPath = file("$buildDir/jacoco/UT/jacocoUT.exec")
       classDumpPath = file("$buildDir/jacoco/UT/classpathdumps")

       //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 }
     ignoreFailures = true

     testClassesDir = sourceSets.integrationTest.output.classesDir
     classpath = sourceSets.integrationTest.runtimeClasspath

     testReportDir = file("$buildDir/reports/tests/IT")
     testResultsDir = file("$buildDir/test-results/IT")

     //Following Jacoco test section is required only in Jenkins instance extra common file
     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

      executionData = fileTree(dir: 'build/jacoco', include: '**/*.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"
             }
      }

      //sourceDirectories = files(sourceSets.main.allJava.srcDirs)
      sourceDirectories = files('src/java')
      classDirectories =  files('build/classes/main')

      //------------------------------------------
      //additionalSourceDirs = files('test/java')
      //additionalSourceDirs += files('src/java-test')

      //additionalClassDirs = files('build/classes/test')
      //additionalClassDirs += files('build/classes/integrationTest')
      //additionalClassDirs += files('build/classes/acceptanceTest')
      //------------------------------------------
  }



我的问题: 1.当我不使用“apply plugin:'jacoco'”时,测试任务成功运行(我只有一个测试)。但是,当我启用apply plugin:'jacoco'时,然后在:test task期间,我在构建输出期间看到以下行,并且该过程只是挂起并坐了几个小时而且没有继续。

Starting process 'Gradle Worker 1'. Working directory: /production/jenkinsAKS/workspace/MyProjectSvc Command: /production/jdk1.6.0_03/bin/java -Djava.security.manager=jarjar.org.gradle.processinternal.child.BootstrapSecurityManager -javaagent:build/tmp/expandedArchives/org.jacoco.agent-0.7.0.201403182114.jar_2kiqpmj1hlqbuth11j0qnuarhs/jacocoagent.jar=destfile=build/jacoco/UT/jacocoUT.execappend=true,dumponexit=true,output=file,classdumpdir=build/jacoco/UT/classpathdumps,jmx=false -Dfile.encoding=UTF-8 -ea -cp /production/jenkins/.gradle/caches/1.6/workerMain/gradle-worker.jar jarjar.rg.gradle.process.internal.launcher.GradleWorkerMain
An attempt to initialize for well behaving parent process finished.
Successfully started process 'Gradle Worker 1'
Gradle Worker 1 executing tests.
> Building > :test

我google了一下,似乎在当前的最新版本中Jacoco和JMockit库之间存在一些不兼容性,并且有一个解决办法可以解决这个问题。新版本的Jacoco 0.7.1.xxxxx有修复,但我不知道它何时可以在Maven存储库中使用。

任何想法,如何设置javaagent忽略JACOCO的测试/测试类文件,仍然应用jacoco插件。在我的例子中,应用插件:'jacoco'稍后将存在于一个全局文件中,即在allProjects {....}部分的/init.d/global-common.gradle文件中。

我尝试了以下但仍然,构建过程挂起:测试任务,直到我取消注释排除在下面。如果我在测试部分中注释掉整个jacoco子部分,那么构建过程仍然会挂起:测试任务(看起来像应用插件:'jacoco'就在那里)。

如果我取消注释exlude,那么我没有看到错误但是没有测试运行,即测试报告的index.html显示没有运行。

test {
     include "**/*"
     jacoco {
        //exclude "**/util/Test*"
     }
}

2。如何在我的build.gradle文件中使用jacoco 0.7.1.xxxx版本(非发行版,即每晚发行版,其中包含此问题的修复程序)。当我在取消注释后使用0.7.1.xxx版本时(如上所示),它错误地说无法找到依赖关系jacoco:0.7.1.xxxx

3.为了摆脱这个问题,我想我可以设置一个jacoco代理参数,即当它运行时,它将忽略JMOckit / JUnit .jar库或其他东西。查看/找到以下链接:
    http://javaee.ch/2012/10/09/jmockit-with-maven-sonar-jacoco-and-jenkinshudson/
https://github.com/jacoco/jacoco/pull/35

度Acc。到第二个链接:

避免此问题的解决方法是从JaCoCo的考虑中排除JUnit类。我在测试中使用了以下JVM初始化参数,不包括JUnit和TestNG类:-javaagent:/jacoco-0.7.1/lib/jacocoagent.jar=excludes=junit。:org.junit。 :org.testng。 好消息是我在之前的评论中描述的修复也解决了这个死锁问题,因为JCoit类将被JMockit检测,因为它们会被JaCoCo忽略。

我正在尝试在jacoco {...}或test {...}中找到哪个变量我可以设置为相同,直到我获得新版本的Jacoco或JMockit(具有修复)。
看起来好像是在测试部分,即测试{...有jvmArgs'......'将被设置。 jacoco {...} ..} http://stevendick.github.io/blog/2012/01/22/jacoco-and-gradle/

4.如果我使用“exclude”com / xxx / yyy / a / b / c / util / Testname.class“排除测试类文件,那么它可以工作,我没有看到错误,但后来我发现了这个排除,我的测试永远不会运行!    这就是它没有挂起的原因。好吧,我希望测试运行,不希望Jacoco处理它。

只需将应用插件:build.gradle中的'jacoco'挂起构建于:test task。我需要jacoco,因为开发团队也希望看到代码覆盖率细节。

目前,我正在尝试找到上述问题的答案,感谢您的投入。

3 个答案:

答案 0 :(得分:3)

最终答案:

Jmockit和Jacoco都是类文件的工具。 Jmockit在构建过程中首先执行此操作,当jacoco尝试相同时(在此过程的后期),它会说"哦,哦,无法检测已经检测过的类文件"。这个问题发生在旧版本的jacoco和jmockit上。要查看此错误,请在Gradle构建期间启用--stacktrace选项或--debug。

现在,使用最新的jacoco和jmockit版本,我们可以轻松解决这个问题。

如果你使用jacoco:

toolVersion="0.7.1.201405082137"

toolVersion="0.7.2.201409121644"

请参阅:0.7.1版本中的更改 http://www.eclemma.org/jacoco/trunk/doc/changes.html

对于JMockit,你必须至少使用jmockit版本:1.8(1.9到1.13)。

org.jmockit:jmockit:1.8

请参阅:1.8版本下的更改:http://jmockit.github.io/changes.html

答案 1 :(得分:0)

答案1:设置jacoco子部分(在测试部分内) - 启用字段为“false”就可以了。我没有获得代码覆盖率(我可以使用它直到我为JMockit / Jacoco获取新版本)但现在我看到有效的测试报告index.html文件(即测试成功运行)并仍然应用插件:' jacoco'可以在/init.d/global-common.gradle文件中保持有效...

test {
     jacoco {
        enabled false
     }
}

对于答案2:到目前为止尚未找到,将分享。

答案3:未解决错误 - 但是如何设置错误的链接:http://stevendick.github.io/blog/2012/01/22/jacoco-and-gradle/

我试过给,可能是我没有正确使用它。 jvmArgs'....:,....:..,....:....,exclude =“com。:org.gradle。; jmockit。: 。mockit :的junit *“

答案4:答案1就足够了。

答案 2 :(得分:0)

我对gradle不太熟悉,所以我不确定我可以帮助解决问题1,3或4 ...

但问题2,我可以提供帮助 - JaCoCo 0.7.1的版本字符串不是0.7.1.201404171759,而是0.7.1.201405082137。这个版本已经正式发布,万一你没有注意到。

如果您想要最新的每晚构建,那么惯例就是简单地引用0.7.2-SNAPSHOT(确保您指向https://oss.sonatype.org/content/repositories/snapshots/处的快照存储库)。