如何向 Gradle 添加新的源集?

我想添加集成测试到我的 Gradle 构建(版本1.0)。它们应该与我的正常测试分开运行,因为它们需要将一个 webapp 部署到 localhost (它们测试那个 webapp)。测试应该能够使用在我的主源代码集中定义的类。我该怎么做?

132804 次浏览

2021年最新情况:

八年来发生了很多变化。分级仍然是一个伟大的工具。现在,文档中有一个完整的部分专门用于配置集成测试。我现在向你推荐 看看文件

原答案:

我花了一段时间才弄明白,而且网上的资源也不是很好。所以我想记录我的解决方案。

这是一个简单的 gradle 构建脚本,除了主源代码集和测试源代码集之外,还有一个 intTest 源代码集:

apply plugin: "java"


sourceSets {
// Note that just declaring this sourceset creates two configurations.
intTest {
java {
compileClasspath += main.output
runtimeClasspath += main.output
}
}
}


configurations {
intTestCompile.extendsFrom testCompile
intTestRuntime.extendsFrom testRuntime
}


task intTest(type:Test){
description = "Run integration tests (located in src/intTest/...)."
testClassesDir = project.sourceSets.intTest.output.classesDir
classpath = project.sourceSets.intTest.runtimeClasspath
}

下面是我如何在不使用 configurations{ }的情况下做到这一点的。

apply plugin: 'java'


sourceCompatibility = JavaVersion.VERSION_1_6


sourceSets {
integrationTest {
java {
srcDir 'src/integrationtest/java'
}
resources {
srcDir 'src/integrationtest/resources'
}
compileClasspath += sourceSets.main.runtimeClasspath
}
}


task integrationTest(type: Test) {
description = "Runs Integration Tests"
testClassesDir = sourceSets.integrationTest.output.classesDir
classpath += sourceSets.integrationTest.runtimeClasspath
}

使用: Gradle 1.4和 Gradle 1.6进行测试

This was 2016年曾经为2.x/3.x 年级写过,现在已经过时了!! Please have a look at the documented solutions in Gradle 4 and up


To sum up both old answers (get best and minimum viable of both worlds):

一些温暖的话首先:

  1. 首先,我们需要定义 sourceSet:

    sourceSets {
    integrationTest
    }
    
  2. next we expand the sourceSet from test, therefor we use the test.runtimeClasspath (which includes all dependenciess from test AND test itself) as classpath for the derived sourceSet:

    sourceSets {
    integrationTest {
    compileClasspath += sourceSets.test.runtimeClasspath
    runtimeClasspath += sourceSets.test.runtimeClasspath // ***)
    }
    }
    
    • 不知怎么的,这个 sourceSets.integrationTest.runtimeClasspath的重新声明/扩展是必需的,但是应该是不相关的,因为 runtimeClasspath总是扩展 output + runtimeSourceSet,不要得到它
  3. 我们为运行集成测试定义了一个专门的任务:

    task integrationTest(type: Test) {
    }
    
  4. Configure the integrationTest test classes and classpaths use. The defaults from the java plugin use the test sourceSet

    task integrationTest(type: Test) {
    testClassesDir = sourceSets.integrationTest.output.classesDir
    classpath = sourceSets.integrationTest.runtimeClasspath
    }
    
  5. (optional) auto run after test

    integrationTest.dependsOn test
    

  6. (optional) add dependency from check (so it always runs when build or check are executed)

    tasks.check.dependsOn(tasks.integrationTest)
    
  7. (optional) add java,resources to the sourceSet to support auto-detection and create these "partials" in your IDE. i.e. IntelliJ IDEA will auto create sourceSet directories java and resources for each set if it doesn't exist:

    sourceSets {
    integrationTest {
    java
    resources
    }
    }
    

tl;dr

apply plugin: 'java'


// apply the runtimeClasspath from "test" sourceSet to the new one
// to include any needed assets: test, main, test-dependencies and main-dependencies
sourceSets {
integrationTest {
// not necessary but nice for IDEa's
java
resources


compileClasspath += sourceSets.test.runtimeClasspath
// somehow this redeclaration is needed, but should be irrelevant
// since runtimeClasspath always expands compileClasspath
runtimeClasspath += sourceSets.test.runtimeClasspath
}
}


// define custom test task for running integration tests
task integrationTest(type: Test) {
testClassesDir = sourceSets.integrationTest.output.classesDir
classpath = sourceSets.integrationTest.runtimeClasspath
}
tasks.integrationTest.dependsOn(tasks.test)

指:

不幸的是,Github.com/gradle/gradle/subprojects/docs/src/samples/java/customizedlayout/build.gradle.../gradle/.../with IntegrationTest/build.gradle上的示例代码似乎没有处理这个问题,或者有一个不同的/更复杂的/对我来说没有更清晰的解决方案!

星云切面插件消除了样板:

apply plugin: 'nebula.facet'
facets {
integrationTest {
parentSourceSet = 'test'
}
}

对于集成测试,甚至是 这是为你准备的,只需应用:

apply plugin: 'nebula.integtest'

对于每个网站的 Gradle 插件门户链接如下:

  1. 星云,方面
  2. nebula.integtest

Here's what works for me as of Gradle 4.0.

sourceSets {
integrationTest {
compileClasspath += sourceSets.test.compileClasspath
runtimeClasspath += sourceSets.test.runtimeClasspath
}
}


task integrationTest(type: Test) {
description = "Runs the integration tests."
group = 'verification'
testClassesDirs = sourceSets.integrationTest.output.classesDirs
classpath = sourceSets.integrationTest.runtimeClasspath
}

在4.0版本中,Gradle 现在为源代码集中的每种语言使用单独的类目录。因此,如果您的构建脚本使用 sourceSets.integrationTest.output.classesDir,您将看到以下弃用警告。

Gradle 现在为每种 JVM 语言使用单独的输出目录,但是这个构建假设源集中的所有类都有一个单独的目录。这种行为已经遭到反对,并计划在 Gradle 5.0版本中删除

要消除这个警告,只需切换到 sourceSets.integrationTest.output.classesDirs

如果你吸毒的话

  • 5. x 级,查看 < a href = “ https://docs.Gradle.org/5.2.1/userguide/Java _ Testing.html # sec: Configuring _ Java _ Integration _ test”rel = “ noReferrer”> 文档部分“测试 Java > 配置集成测试 有关详细信息的示例14和15(均适用于 Groovy 和 Kotlin DSL,您可以选择其中一种)
    • Alt: “当前”的 Gradle doc 链接在 2,但可能推迟在未来,你应该有一个看看,如果例子的变化)
  • 对于四年级看看古代版本的 3,这是接近什么 @ Spina 发布于2012年

要让 IntelliJ 识别自定义源集作为测试源根:

plugin {
idea
}


idea {
module {
testSourceDirs = testSourceDirs + sourceSets["intTest"].allJava.srcDirs
testResourceDirs = testResourceDirs + sourceSets["intTest"].resources.srcDirs
}
}

我刚到 Gradle,使用的是 Gradle 6.0.1 jun4.12。

apply plugin: 'java'
repositories { jcenter() }


dependencies {
testImplementation 'junit:junit:4.12'
}


sourceSets {
main {
java {
srcDirs = ['src']
}
}
test {
java {
srcDirs = ['tests']
}
}
}

注意,主源代码和测试源代码是分开引用的,一个在 main下,一个在 test下。

dependencies下的 testImplementation项只用于在 test中编译源代码。如果您的主代码实际上依赖于 JUnit,那么您还应该在 dependencies下指定 implementation

我必须指定 repositories部分才能让它工作,我怀疑这是最好的/唯一的方法。

我知道在2012年当这个问题被问及时,文档并不是很好,但是对于在2020年以后阅读这篇文章的人来说: 现在文档中有一整节是关于 如何为集成测试添加源代码集的。你真的应该读读它,而不是在这里复制/粘贴代码片段,然后用脑袋撞墙,试图找出为什么2012-2016年的答案不太管用。

答案很可能很简单,但是比你想象的更加微妙,你需要的确切代码很可能与我需要的代码不同。例如,您希望集成测试使用与单元测试相同的依赖项吗?