简体   繁体   English

如何向 Gradle 添加新的源集?

[英]How do I add a new sourceset to Gradle?

I want to add integration tests to my Gradle build (Version 1.0).我想将集成测试添加到我的 Gradle 构建(版本 1.0)中。 They should run separately from my normal tests because they require a webapp to be deployed to localhost (they test that webapp).它们应该与我的正常测试分开运行,因为它们需要将 webapp 部署到本地主机(它们测试该 webapp)。 The tests should be able to use classes defined in my main source set.测试应该能够使用我的主要源集中定义的类。 How do I make this happen?我该如何做到这一点?

Update for 2021: 2021 年更新:

A lot has changed in 8ish years. 8 岁左右发生了很多变化。 Gradle continues to be a great tool. Gradle 仍然是一个很棒的工具。 Now there's a whole section in the docs dedicated to configuring Integration Tests.现在文档中有一整节专门用于配置集成测试。 I recommend you read the docs now.我建议您现在阅读文档

Original Answer:原答案:

This took me a while to figure out and the online resources weren't great.这花了我一段时间才弄明白,而且在线资源也不是很好。 So I wanted to document my solution.所以我想记录我的解决方案。

This is a simple gradle build script that has an intTest source set in addition to the main and test source sets:这是一个简单的 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
}

Here is how I achieved this without using configurations{ } .以下是我如何在不使用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
}

Tested using: Gradle 1.4 and Gradle 1.6测试使用: Gradle 1.4 和 Gradle 1.6

This was once written for Gradle 2.x / 3.x in 2016 and is far outdated !!曾经是在 2016 年为 Gradle 2.x / 3.x 编写的并且已经过时了 Please have a look at the documented solutions in Gradle 4 and up请查看Gradle 4 及更高版本中记录的解决方案


To sum up both old answers (get best and minimum viable of both worlds):总结两个旧答案(获得两个世界的最佳和最小可行):

some warm words first:先说几句暖心话:

  1. first, we need to define the sourceSet :首先,我们需要定义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 :接下来我们从test扩展sourceSet ,因此我们使用test.runtimeClasspath (包括来自testtest本身的所有依赖项)作为派生sourceSet的类路径:

     sourceSets { integrationTest { compileClasspath += sourceSets.test.runtimeClasspath runtimeClasspath += sourceSets.test.runtimeClasspath // ***) } }
    • note ) somehow this redeclaration / extend for sourceSets.integrationTest.runtimeClasspath is needed, but should be irrelevant since runtimeClasspath always expands output + runtimeSourceSet , don't get it注意)不知何故,需要重新声明/扩展sourceSets.integrationTest.runtimeClasspath ,但应该无关紧要,因为runtimeClasspath总是扩展output + runtimeSourceSet ,不要理解它
  3. we define a dedicated task for just running integration tests:我们定义了一个专门用于运行集成测试的任务:

     task integrationTest(type: Test) { }
  4. Configure the integrationTest test classes and classpaths use.配置integrationTest测试类和类路径使用。 The defaults from the java plugin use the test sourceSet java插件的默认值使用test sourceSet

     task integrationTest(type: Test) { testClassesDir = sourceSets.integrationTest.output.classesDir classpath = sourceSets.integrationTest.runtimeClasspath }
  5. (optional) auto run after test (可选)测试后自动运行

    integrationTest.dependsOn test integrationTest.dependsOn 测试

  6. (optional) add dependency from check (so it always runs when build or check are executed) (可选)check中添加依赖项(因此它始终在执行buildcheck时运行)

     tasks.check.dependsOn(tasks.integrationTest)
  7. (optional) add java,resources to the sourceSet to support auto-detection and create these "partials" in your IDE. (可选)将 java,resources 添加到sourceSet以支持自动检测并在您的 IDE 中创建这些“部分”。 ie IntelliJ IDEA will auto create sourceSet directories java and resources for each set if it doesn't exist:即 IntelliJ IDEA 将自动为每个集合创建sourceSet目录 java 和资源(如果它不存在):

     sourceSets { integrationTest { java resources } }

tl;dr tl;博士

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)

referring to:参考:

Unfortunatly, the example code on github.com/gradle/gradle/subprojects/docs/src/samples/java/customizedLayout/build.gradle or …/gradle/…/withIntegrationTests/build.gradle seems not to handle this or has a different / more complex / for me no clearer solution anyway!不幸的是,github.com/gradle/gradle/subprojects/docs/src/samples/java/customizedLayout/ build.gradle…/gradle/…/withIntegrationTests/build.gradle上的示例代码似乎无法处理此问题或具有不同的/更复杂/对我来说没有更清晰的解决方案!

The nebula-facet plugin eliminates the boilerplate: nebula-facet插件消除了样板文件:

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

For integration tests specifically, even this is done for you , just apply:特别是对于集成测试,即使这是为您完成的,只需申请:

apply plugin: 'nebula.integtest'

The Gradle plugin portal links for each are:每个的 Gradle 插件门户链接是:

  1. nebula.facet星云面
  2. nebula.integtest星云.integtest

If you're using如果你正在使用

To get IntelliJ to recognize custom sourceset as test sources root:要让 IntelliJ 将自定义源集识别为测试源根:

plugin {
    idea
}

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

Here's what works for me as of Gradle 4.0.从 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
}

As of version 4.0, Gradle now uses separate classes directories for each language in a source set.从 4.0 版开始,Gradle 现在为源集中的每种语言使用单独的类目录。 So if your build script uses sourceSets.integrationTest.output.classesDir , you'll see the following deprecation warning.因此,如果您的构建脚本使用sourceSets.integrationTest.output.classesDir ,您将看到以下弃用警告。

Gradle now uses separate output directories for each JVM language, but this build assumes a single directory for all classes from a source set. Gradle 现在为每种 JVM 语言使用单独的输出目录,但此构建假设源集中的所有类都使用一个目录。 This behaviour has been deprecated and is scheduled to be removed in Gradle 5.0此行为已被弃用,并计划在 Gradle 5.0 中删除

To get rid of this warning, just switch to sourceSets.integrationTest.output.classesDirs instead.要消除此警告,只需切换到sourceSets.integrationTest.output.classesDirs For more information, see the Gradle 4.0 release notes .有关详细信息,请参阅Gradle 4.0 发行说明

I gather the documentation wasn't great back in 2012 when this question was asked, but for anyone reading this in 2020+: There's now a whole section in the docs about how to add a source set for integration tests .我收集到的文档在 2012 年提出这个问题时并不是很好,但是对于在 2020 年以后阅读此文档的任何人:文档中现在有一整节关于如何为集成测试添加源集 You really should read it instead of copy/pasting code snippets here and banging your head against the wall trying to figure out why an answer from 2012-2016 doesn't quite work.您真的应该阅读它,而不是在此处复制/粘贴代码片段,然后用头撞墙试图弄清楚为什么 2012-2016 年的答案不太管用。

The answer is most likely simple but more nuanced than you may think, and the exact code you'll need is likely to be different from the code I'll need.答案很可能很简单,但比您想象的更微妙,而且您需要的确切代码可能与我需要的代码不同。 For example, do you want your integration tests to use the same dependencies as your unit tests?例如,您是否希望集成测试使用与单元测试相同的依赖项?

You might also want to configure your tests to run with jUnit:您可能还想将测试配置为使用 jUnit 运行:

task integrationTest(type: Test) {
   ...
   useJunitPlatform()
}

I'm new to Gradle, using Gradle 6.0.1 JUnit 4.12.我是 Gradle 的新手,使用 Gradle 6.0.1 JUnit 4.12。 Here's what I came up with to solve this problem.这是我想出的办法来解决这个问题。

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

dependencies {
    testImplementation 'junit:junit:4.12'
}

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

Notice that the main source and test source is referenced separately, one under main and one under test .请注意,主要源和测试源是分开引用的,一个在main下,一个在 under test下。

The testImplementation item under dependencies is only used for compiling the source in test . dependencies下的testImplementation项仅用于编译test中的源代码。 If your main code actually had a dependency on JUnit, then you would also specify implementation under dependencies .如果您的主要代码实际上依赖于 JUnit,那么您还需要在dependencies下指定implementation

I had to specify the repositories section to get this to work, I doubt that is the best/only way.我必须指定repositories部分才能使其正常工作,我怀疑这是最好/唯一的方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM