【问题标题】:Programmatically invoke a gradle task graph in a unit test在单元测试中以编程方式调用 gradle 任务图
【发布时间】:2013-04-28 16:23:32
【问题描述】:

我正在为 gradle 编写自定义插件,作为单元测试的一部分,我想调用我的任务,但前提是它的先决任务已被执行。

不幸的是,实际的插件是一个内部项目,所以我不能确定确切的来源,但我已经准备了一个单元测试来演示这个问题:

package toy

import org.gradle.api.Project
import org.gradle.testfixtures.ProjectBuilder
import org.junit.Test

class ToyTasksTest {

    boolean task1Run = false
    boolean task2Run = false

    @Test
    public void taskDependencies(){


        Project p = ProjectBuilder.builder().build()

        p.task("task1") << {
            p.logger.info("task1 running")
            task1Run = true
        }

        def task2 = p.task("task2", dependsOn: 'task1') << {
            p.logger.info("task2 running")
            task2Run = true
        }
        task2.execute() // <--- what magic do I need here instead of .execute()

        assert task2Run == true
        assert task1Run == true
    }
}

输出是:

Assertion failed: 

assert task2Run == true
       |        |
       false    false

如果您想快速运行测试,该项目是available on github

另一种说法而不是写作:

task2.execute()

我想运行相当于:

gradle task2

在单元测试中。

【问题讨论】:

  • 在我遇到的大多数情况下,Gradle TestKit 通常比ProjectBuilder 效果更好。
  • 是的,我相信现在就是这种情况。

标签: gradle gradle-custom-plugin


【解决方案1】:

在我看来,您在这里尝试的更多是集成测试而不是单元测试。 Gradle 团队成员过去曾向我建议,在编写插件和任务时,您想要做的是尽可能多地/有意义地从您的任务中分离到 POJO 并对其进行单元测试。对于 Gradle 为您和管道所做的所有其他事情,例如执行任务图、测试增量任务功能等,您可能希望进行绝对较慢的集成测试,这就是您希望尽可能多地进行单元测试的原因。

唯一的问题是 Gradle 目前没有提供用于编写​​这些集成测试的工具集。有一个design spec for that,但目前如果需要,您仍然需要手动制定解决方案。

你可以看看我使用的here,但请记住它有一些类路径问题,这就是为什么this line 是必要的。

我最近发现的另一个使用 GradleConnector 的解决方案的示例可以在 here 找到。

【讨论】:

    【解决方案2】:

    Luke Daley(Gradle 核心开发人员)为我的 Gradle 插件开发了一个很酷的功能测试系统,在使用中看到了 here

    与@erdi 的回答类似,这是一个功能测试解决方案,不使用 Gradle 的 ProjectBuilder。它要求您包含these utility classes 进行测试。

    我意识到这可能不是您希望的简洁答案,但是当我开发一些 Gradle 插件时,这个系统对我很有帮助。

    【讨论】:

    • 我使用的解决方案很大程度上基于(我的意思是复制粘贴)您所指向的解决方案
    【解决方案3】:

    替换:

    task2.execute() // <--- what magic do I need here instead of .execute()
    

    与:

    task2.actions.each { Action action ->
         action.execute(task2)
    }
    

    【讨论】:

    • 唉,这并没有执行问题中描述的依赖项
    • 至少这解决了我的问题,在 gradle 5.3 中没有更多的execute() 方法用于任务
    【解决方案4】:

    我使用这种方法在测试中执行任务:

    void executeTask(Task task) {
        task.taskDependencies.getDependencies(task).each {
            subTask -> executeTask(subTask)
        }
    
        task.execute()
    }
    

    示例:

    @Test
    void testTasksDependency() {
        def first = project.task("first").doLast {
            println "Doing First"
        }
    
        def second = project.task("second", dependsOn: first).doLast {
            println "Doing Second"
        }
    
        def third = project.task("third", dependsOn: second).doLast {
            println "Doing Third"
        }
    
        // Let's call our method
        executeTask(third)
    
        assertTrue(first.state.executed)
        assertTrue(second.state.executed)
        assertTrue(third.state.executed)
    }
    

    输出:

    Doing First
    Doing Second
    Doing Third
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多