Gradle`task.withType()`之后添加的任务的奇怪行为

时间:2016-07-27 19:12:09

标签: gradle build.gradle

我使用Gradle 2.14.1和https://github.com/unbroken-dome/gradle-testsets-plugin添加集成测试任务。我想配置HTML报告的位置。 默认任务使用:

<project>/build/reports/tests

testsets插件配置:

<project>/build/intTest

代表intTest任务,我想:

<project>/build/reports/test
<project>/build/reports/intTest

这是我的配置:

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'org.unbroken-dome.gradle-plugins:gradle-testsets-plugin:1.2.0'
    }
}

apply plugin: 'java'
apply plugin: 'org.unbroken-dome.test-sets'

defaultTasks = ['clean', 'build']

tasks.withType(Test) {
    reports.html.destination = new File(project.reportsDir, name)

    println(it.name + '\t' + reports.html.destination)
}

task wrapper(type: Wrapper) {
    description = 'Defines the common gradle distribution for this project.'
    gradleVersion = '2.14.1'
}

testSets {
    intTest
}

intTest.dependsOn test
check.dependsOn intTest

repositories {
    jcenter()
}

dependencies {
    testCompile 'junit:junit:4.12'
    intTestCompile 'junit:junit:4.12'
}

println('===== final config =====')
println(test.name + '\t' + test.reports.html.destination)
println(intTest.name + '\t' + intTest.reports.html.destination)

(暂时请忽略println语句。)

完整构建后,intTest任务的报告位于错误的位置(默认值),并且应用了标准test任务的配置:

$ ls build/
classes  dependency-cache  intTest  intTest-results  libs  reports  test-results  tmp

$ ls build/reports/
test

我添加了一些输出来查看发生了什么,看起来很奇怪(项目的根目录是'blob'):

test    /home/wujek/blob/build/reports/test
intTest /home/wujek/blob/build/reports/intTest
===== final config =====
test    /home/wujek/blob/build/reports/test
intTest /home/wujek/blob/build/intTest

因此,在tasks.withType()块中,报告的位置是正确的,但最终却没有。

请注意,在tasks.withType()块之后移动testSets块适用于此项目,但我的实际设置模式很复杂:我有多个模块,根build.gradle使用使用subprojectstasks.withType()阻止为所有模块配置报告位置,然后其中一个子模块添加新测试集,其测试任务的HTML报告位置错误。要解决这个问题,我必须在添加测试集的子模块中重复配置。

这里发生了什么?为什么tasks.withType()块说配置有效,但实际上它没有?

1 个答案:

答案 0 :(得分:1)

这是由于Gradle中订购配置的特点。让我们一起浏览您的代码,因为Gradle会处理它以查看会发生什么(跳过不相关的行):

apply plugin: 'org.unbroken-dome.test-sets'

这将执行test-sets插件的apply方法,其中包含the creation of a class which listens for test sets to be addedIt adds a whenObjectAdded actiontestSets容器。您还没有添加任何测试集,所以让我们回到您的build.gradle

tasks.withType(Test) {
    reports.html.destination = new File(project.reportsDir, name)

    println(it.name + '\t' + reports.html.destination)
}

您现在已添加了一项操作,该操作将应用于所有现有Test任务,并在创建新任务时应用于新任务。现在它全部展开:

testSets {
    intTest
}

这会创建一个名为testSet的{​​{1}}。现在,测试集插件中的intTest操作将触发:

  1. whenObjectAdded设置测试任务is created
  2. 您的intTest操作会触发,因为现在有一个新的withType任务。这会将报告设置为您想要的位置。
  3. Test操作现在继续,转到this line,同时设置html报告位置,覆盖您刚设置的内容。
  4. 当你更改它以首先声明whenObjectAdded时:

    1. testSet - 创建测试任务
    2. whenObjectAdded - 设置测试任务的HTML报告位置
    3. whenObjectAdded由您注册
    4. withType会将HTML报告位置设置为您想要的目的地
    5. 没有严格的规则可以避免这种情况,因为插件可以并且确实采用了截然不同的方法来记录他们注册配置操作的方式。通常,我尝试按以下顺序打破build.gradle:

      1. Buildscript块(如果需要)
      2. 应用插件
      3. 设置项目级别属性(组,版本,sourceCompatibility等)
      4. 配置扩展(sourceSets,testSet,配置,依赖项)
      5. 配置任务(direct或withType)
      6. 通常这有助于在我的配置进行更改之前允许触发配置的插件注册默认值。

        仅供参考,Gradle's new, and still incubating, model space旨在帮助解决此配置排序问题。它不会是完美的,但允许订单更明确。