【问题标题】:Gradle test task - Gradle 1.6 and with Gradle 2.3 or laterGradle 测试任务 - Gradle 1.6 和 Gradle 2.3 或更高版本
【发布时间】:2015-09-25 18:56:01
【问题描述】:

我有一个 Java 项目。

PS:在我的项目中,src/test/java中没有任何java程序/源代码。
- 此文件夹仅包含一个空白.txt 文件。

我有两个不同的 Gradle 版本:

  1. Gradle 1.6 与 Java 7(因为 Java 8 不兼容 Gradle 1.6 或任何版本

  2. 另一个版本是:Gradle 2.3 with Java 8。

同时使用上述 Gradle 1.6 + Java7 Gradle 2.3 + Java 8 版本我的项目构建成功

不过,我注意到一件事:在运行构建时,它会自动调用“测试”任务(根据 Gradle 设计,测试任务是免费运行的);我在 Gradle 1.6 + Java7 运行期间发现 --- 我看到以下输出。

:jar
:assemble
:compileTestJava UP-TO-DATE
:processTestResources
:testClasses
:test
:check

你会注意到,它说我没有任何测试源代码(即 src/test/java 不包含任何源代码 Gradle 没有什么新东西可以编译 这一次可能自上次 gradle 运行构建以来没有任何变化),这就是为什么 compileTestJava 任务在其前面显示 UP-TO-DATE 的原因。

但是,:test 任务显示它运行成功。我在 test { .. } 任务中使用了 jacoco(代码覆盖率)部分,然后它实际上运行了该部分(因为 test 任务前面没有 UP-TO-DATE)。 Jacoco 部分未在我的项目的 build.gradle 中定义,但实际上它来自顶级 / GRADLE_HOME/init.d/some-common-top-level.gradle 文件(其中 test { ... has jacoco { ... } .. } 部分)。

如上所述,test 任务没有说 UP-TO-DATE,因此,在 Gradle 构建过程完成后,我可以看到它在 中创建了以下文件夹/文件结构>build/tmp/expandedArchives/org.jacoco.... 文件夹:

$ ls -ltr build/tmp/expandedArchives/
total 4
drwxr-xr-x+ 1 e020001 Domain Users 0 Jul  7 20:45 org.jacoco.agent-0.7.2.201409121644.jar_778m6tp3jrtvcetasufl59dmau

$ ls -ltr build/tmp/expandedArchives/org.jacoco.agent-0.7.2.201409121644.jar_778m6tp3jrtvcetasufl59dmau/
total 272
drwxr-xr-x+ 1 e020001 Domain Users      0 Jul  7 20:58 META-INF
-rwxr-xr-x  1 e020001 Domain Users   2652 Jul  7 20:58 about.html
-rwxr-xr-x  1 e020001 Domain Users 272311 Jul  7 20:58 jacocoagent.jar
drwxr-xr-x+ 1 e020001 Domain Users      0 Jul  7 20:58 org

在我运行 Gradle 2.3 和 Java8 时不会发生同样的情况。

构建成功,但我没有得到包含 jacocoagent.jar 文件的 build/tmp/expandedArchives/org.jacoco.... 文件夹。

任何想法,为什么 Gradle 2.3 没有创建这个 jacoco 特定的 .jar 文件。

使用 Gradle 2.3+Java8,以下输出在 :compileTestJava:test 任务前面显示 UP-TO-DATE(Gradle 不是这种情况1.6 用于 test 任务)。

我运行了“gradle clean build”。

:compileTestJava UP-TO-DATE
:compileTestGroovy UP-TO-DATE
:processTestResources
:testClasses
:test UP-TO-DATE
:check

我需要 Gradle 2.3 在 build/tmp/expandedArchives/org.jacoco..... 文件夹下生成这个 jacocoagent.jar,这样我就可以在下游 Jenkins 作业(运行非单元测试)中使用它项目确实有一些集成测试,我正在下游作业中从父主构建作业(运行 gradle clean build 包括测试任务)中获取 jacocoagent.jar,以便我可以将其传递给 TOMCAT JVM在启动 Tomcat 时(这样我就可以获得 IT 测试的 jacocoIT.exec 代码覆盖率)。但是,在我切换到 Gradle 2.3 后,我没有 src/test/java 的所有项目......现在 jacocoagent.jar 没有被创建,并且 copy artifact plugin 在尝试复制时失败来自父作业的 .jar 文件。

还有一点
使用 Gradle 1.6 + Java7,如果我运行 gradle clean build,它会在 build/tmp/expandedArchives/org.jacoco..... 文件夹中成功创建 jacocoagent.jar,但它只能以这种方式工作当我运行 gradle clean build 或“gradle clean; gradle test”时。

如果我运行 gradle clean build,然后删除 build/tmp 文件夹,现在只需运行:gradle test,它会在两个 :compileTestJava 前面显示 UP-TO-DATE :test 任务并且不会创建包含 jacocoagent.jar 文件的 build/tmp/expandedArchives/org.jacoco.... 文件夹。

有关更多信息,我在为 Gradle 1.6 + java 7 运行 gradle test 任务时附加配置文件运行(即使用 --profile 选项)。 p>

我看到,在配置文件 html 文件中,当 test 任务运行时,它首先按照 Gradle 流程逻辑调用 compileJava,然后测试任务,它也在调用depedencies --- :jacocoAgent(根据依赖项解析选项卡):



但是

使用 Gradle 2.3 + Java8,依赖关系解析/顺序和任务执行步骤是不同的(或与 Gradle 1.6 相比的顺序),用于生成或显示对 jacocoAgent 依赖项的任何引用,因为它甚至没有调用它。



使用 -i(或 --info)选项运行 Gradle1.6 +Java7 测试任务说明了原因即使我没有测试源代码,它也会运行测试任务,看看原因:

Note: Recompile with -Xlint:unchecked for details.
:processResources
Skipping task ':processResources' as it has no source files.
:processResources UP-TO-DATE
:classes
Skipping task ':classes' as it has no actions.
:compileTestJava
Skipping task ':compileTestJava' as it has no source files.
:compileTestJava UP-TO-DATE
:processTestResources
Executing task ':processTestResources' due to:
  No history is available.
:testClasses
Skipping task ':testClasses' as it has no actions.
:test
file or directory '/my/workspace/project/build/classes/test', not found
Executing task ':test' due to:
  No history is available.
file or directory '/my/workspace/project/build/classes/test', not found
Finished generating test XML results (0.001 secs)
Generating HTML test report...
Finished generating test html results (0.012 secs)

BUILD SUCCESSFUL

【问题讨论】:

  • 您能否在启用“-i”标志的情况下运行 Gradle 1.6 + Java7。这告诉你为什么 gradle 运行这个任务并且确实认为测试任务不是最新的。我想有一些变化
  • 我运行“rm -fr .gradle”(删除任何本地 gradle 缓存),运行“gradle clean”。现在,我运行了 gradle test -i(用于显示 --info)。它显示: :compileTestJava 跳过任务 ':compileTestJava' 因为它没有源文件。:compileTestJava UP-TO-DATE。然后, :processTestResources 执行任务 ':processTestResources' 由于: 没有可用的历史记录。然后, :testClasses 跳过任务 ':testClasses' 因为它没有任何动作。然后,:test文件或目录'/production/home/c400093/giga/OCMPayerOnline/build/classes/test',找不到
  • 执行任务 ':test' 由于:没有可用的历史记录。文件或目录“/my/workspace/project/build/classes/test”,未找到符合预期的文件或目录。
  • 啊,我明白了。如果您将其添加到您的构建中是否有帮助:test {doFirst { file("build/classes/test").mkdirs()}}
  • 是的,我同意你为什么 compileTestJava 说 UP-TO-DATE (这是预期的,因为我没有任何测试代码)但测试任务仍然运行(没有显示 UP-TO-DATE ) 使用 Gradle1.6+Java7。我用 -i output 粘贴了上面的原因

标签: unit-testing gradle jacoco gradle-2


【解决方案1】:

无论输入和输出的状态如何,您都可以强制执行测试任务:

test{
    outputs.upToDateWhen{false}
}

对于早期的 gradle 版本,您可以通过以下方式确保类目录存在

task createTestClassesDir << {sourceSets.test.output.classesDir.mkdirs()}
test.dependsOn createTestClassesDir

【讨论】:

  • 谢谢雷内。我试过了,它不适用于 Gradle 2.3 + Java8。这就是说,无论如何,只需运行任务(测试)。与 Gradle 2.3 一样,运行测试任务(清理后)已经显示为 UP-TO-DATE。我将发布您想要的 -i 选项的输出。我刚刚用 Gradle 1.6+Java7 ..和 Gradle 2.3+Java8 的 --profile 输出更新了我的问题。我正在尝试让 Gradle2.3 + Java8 调用那些 :testRuntime 和 :jacocoAgent 依赖项...以便它可以创建包含该文件的 build/tmp/exapandedArchives/org.jacoco... 文件夹。
  • 我尝试了上面的 createTestClassDir 解决方法,它创建了 build/classes/test 文件夹,但是 :test 任务仍然说:跳过任务 ':test' 因为它没有源文件。 :test UP-TO-DATE :test ...耗时 0.001 秒。
  • 我有一个解决方案,我会在验证后立即分享。与 Gradle 2.3 一样,我们必须有有效的源测试 java / groovy 代码才能实际运行“:test”任务(这也将在 build/tmp/expandedArchives/org.jacoco.. 文件夹中创建 jacocoagent.jar,前提是您有jacoco { .. } 部分定义在测试任务中),想法是,我们需要在 src/test/java 文件夹中创建一个有效的 DummyTest.java 文件,创建 src/test/java 文件夹以防万一它不存在,只需创建compileJava { doLast { ..section.. } } 中的虚拟 java 文件,然后在 test { doLast { ...section ..} } 中,我们需要做更多。
  • 在 test { ... doLast {... section ... } } 中,我们必须删除 DummyTest.java 文件,删除 src/test/java 文件夹(如果它是由我们的解决方法创建的) (否则,使用 FLAG 变量会有所帮助,我们不会删除此文件夹),然后删除 build/classes/test 文件夹,最后删除 build/jacoco/jacoco.exec 文件以进行单元测试(如果有,则取决于 FLAG)。这样,对于在 src/test/java 中没有任何有效 java 文件或根本没有 src/test/java 的任何项目,测试任务都将运行。就我而言,我们在 build/jacoco/UT 目录中创建 jacocoUT.exe(用于单元测试)。
【解决方案2】:

总结:

使用 Gradle 2.3,如果没有有效的 .java/.groovy(或其他)测试代码,则 test 任务甚至不会运行,因此不会创建 jacocoagent.jar在 build/tmp/exapandedArchives/org.jacoco.xxx.... 文件夹深处的某个地方。

解决方案是在 allprojects { .... } 部分中包含以下内容(在顶级 $GRADLE_HOME/init.d/some-global-file.gradle 中)。我们所做的只是,如果 src/test/java(标准)或任何遗留文件夹结构(如果您的项目结构是这样的,则为 src/java)没有任何有效的测试源代码,那么我们可以添加一个虚拟测试文件(DummyTestXYZ.java 或 groovy)并让测试任务运行,这将生成 jacocoagent.jar(我们可以使用/绑定在 Tomcat 选项中为非单元也称为集成测试生成 jacoco 报告)。这样,如果您的主构建作业调用下游/子作业来运行您的 IT 测试,它不会失败,因为它可以获取 jacocoagent.jar(从主构建作业的工作区),因为测试任务将在 build/ 创建 jacocoagent.jar tmp/expandedArchives/org.jacoco.xx.x.xx..x 文件夹(您可以使用 Jenkins 中的 Copy Artifact 插件获得)。

PS:更改if语句逻辑acc。到您自己的文件夹设置,即您要在哪个文件夹中创建 DummyTestXYZ.java 文件。在我们的案例中,所有新项目都使用 src/test/java(根据 Maven/Gradle 标准的标准文件夹结构),并且在新项目创建期间,我们正在将有效的示例单元测试签入到源代码控制中。因此,在下面的逻辑中,我们实际上忽略了在 src/test/java 存在的情况下创建这个 DummyTestXYZ.java 并且仅当 src/test/java 文件夹中不存在时才创建这个文件项目(即这是一个具有遗留文件夹结构的项目)+ test/java(用于存储 JUnit 单元测试的遗留文件夹)没有 .java 程序和/或如果 test/java 不存在,则先创建它,然后再创建虚拟文件。我知道,我们可以在 Jenkins 服务器上的某个位置上传 jacocoagent.jar,并在启动 Tomcat 时使用该文件来获取 IT 测试的代码覆盖率。我们添加的虚拟测试文件需要 junit:junit:4.10 或 4.11 库版本才能使 :compileTestJava 任务成功。

   compileJava {
    doLast {
        def dirName = "${projectDir}/test/java"

        if(!file( "${projectDir}/src/test/java" ).exists()) 
            if(!file( dirName ).exists()) 
                new File( dirName ).mkdirs()

        if(file( dirName ).exists()) {
            def javaCnt = new FileNameByRegexFinder().getFileNames(dirName, /.*\.java/).size()
            if(javaCnt == 0) {
                def f = new File( dirName , 'DummyTestXYZ.java' )
                def w = f.newPrintWriter()
                w.println('import org.junit.Test;')
                w.println('')
                w.println('public class DummyTestXYZ {')
                w.println('@Test' )
                w.println('public void test() {')
                w.println('}')
                w.println('}')
                w.close()
            }
        }
    }
   }

   test {
     doFirst {
              testResultsDirName = "test-results/UT"
              testReportDirName = "tests/UT"
     }         
     maxParallelForks = 5
     forkEvery = 50
     //ignoreFailures = true

     // Following Jacoco section is required only in Jenkins
     // But a developer can uncomment them if they want this feature to work for their 
     // Desktop local Gradle builds.
     jacoco {
            //Following vars works only with versions >= 1.7 version of Gradle
            destinationFile = file("$buildDir/jacoco/UT/jacocoUT.exec")
     }

     doLast {
        if (file("${projectDir}/test/java/DummyTestXYZ.java").exists()) {
            println "++"
            println "++"
            println "++"
            println "======================================================="
            println "DEV Team – Please add valid Unit tests in this project."
            println "======================================================="
            println "++"
            println "++"
            println "++"
            sleep(30 * 1000)
            new File("${projectDir}/build/classes/test").deleteDir()
            new File("${buildDir}/jacoco/UT").deleteDir()
            new File("${buildDir}/test-results/UT").deleteDir()
            delete "${projectDir}/test/java/DummyTestXYZ.java"
         }


     }
   }
   //Do the same (as above test code) for any other similar test tasks like integartionTest, acceptanceTest etc..

  jacocoTestReport {
     //cleaning any compile time generated (for ex: JiBx classes files) so that jacoco task won't fail for not finding the actual source files (.java/.groovy for the compile time generated .class files)
     doFirst {
         delete fileTree (dir: "${buildDir}/classes", include: "**/JiBX_*.class")
     }

     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(['src/java','src/main/java', 'src/main/groovy'])
     classDirectories =  files('build/classes/main')

     doLast {
        if (file("${projectDir}/test/java/DummyTestXYZ.java").exists()) {
            delete "${projectDir}/test/java/DummyTestXYZ.java"
         }
     }
   }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-16
    • 2020-03-16
    • 2015-01-10
    • 2017-12-24
    • 1970-01-01
    • 2014-03-14
    • 2017-07-28
    相关资源
    最近更新 更多