使用gradle的多项目测试依赖项

时间:2011-04-13 03:17:32

标签: build dependencies gradle multi-project

我有一个多项目配置,我想使用gradle。

我的项目是这样的:

  • 项目A

    • - > src/main/java
    • - > src/test/java
  • 项目B

    • - > src/main/java(取决于项目A 上的src/main/java
    • - > src/test/java(取决于项目A 上的src/test/java

我的 Project B build.gradle文件是这样的:

apply plugin: 'java'
dependencies {
  compile project(':ProjectA')
}

任务compileJava效果很好,但compileTestJava无法从项目A 编译测试文件。

15 个答案:

答案 0 :(得分:106)

已过时

项目B 中,您只需要添加testCompile依赖项:

dependencies {
  ...
  testCompile project(':A').sourceSets.test.output
}

使用Gradle 1.7进行测试。

答案 1 :(得分:51)

简单的方法是在ProjectB中添加显式任务依赖:

compileTestJava.dependsOn tasks.getByPath(':ProjectA:testClasses')

困难(但更清晰)的方法是为ProjectA创建其他工件配置:

task myTestsJar(type: Jar) { 
  // pack whatever you need...
}

configurations {
  testArtifacts
}

artifacts {
   testArtifacts myTestsJar
}

并为ProjectB添加testCompile依赖项

apply plugin: 'java'
dependencies {
  compile project(':ProjectA')
  testCompile project(path: ':ProjectA', configuration: 'testArtifacts')
}

答案 2 :(得分:40)

现在已在Gradle中支持此功能。带有javajava-library插件的模块还可以包括一个java-test-fixtures插件,用于公开帮助程序类。和testFixtures助手要消耗的资源。这种方法对工件和分类器的好处是:

  • 适当的依赖项管理(实现/ api)
  • 与测试代码很好地分离(分离的源集)
  • 无需过滤测试类以仅公开实用程序
  • 由Gradle维护

示例

:modul:one

modul / one / build.gradle

plugins {
  id "java-library" // or "java"
  id "java-test-fixtures"
}

modul / one / src / testFixtures / java / com / example / Helper.java

package com.example;
public class Helper {}

:modul:other

modul / other / build.gradle

plugins {
  id "java" // or "java-library"
}
dependencies {
  testImplementation(testFixtures(project(":modul:one")))
}

modul / other / src / test / java / com / example / other / SomeTest.java

package com.example.other;
import com.example.Helper;
public class SomeTest {
  @Test void f() {
    new Helper(); // used from :modul:one's testFixtures
  }
}

进一步阅读

有关更多信息,请参见文档:
https://docs.gradle.org/current/userguide/java_testing.html#sec:java_test_fixtures

它是在5.6中添加的:
https://docs.gradle.org/5.6/release-notes.html#test-fixtures-for-java-projects

答案 3 :(得分:17)

我知道这是一个老问题,但我遇到了同样的问题,花了一些时间弄清楚发生了什么。我正在使用Gradle 1.9。所有更改都应在ProjectB的build.gradle

在ProjectB的测试中使用ProjectA中的测试类:

testCompile files(project(':ProjectA').sourceSets.test.output.classesDir)

确保ProjectA的sourceSets属性可用:

evaluationDependsOn(':ProjectA')

要确保ProjectA中的测试类实际存在,当您编译ProjectB时:

compileTestJava.dependsOn tasks.getByPath(':ProjectA:testClasses')

答案 4 :(得分:13)

我最近自己也遇到过这个问题,而男人这是一个难以找到答案的问题。

你所犯的错误是认为项目应该以导出它的主要工件和依赖项的方式导出它的测试元素。

我个人在Gradle上创建了一个新项目取得了很大的成功。在你的例子中,我会命名为

项目A_Test - >的src /主/ JAVA

我会把你目前在Project A / src / test / java中拥有的文件放到src / main / java中。使项目A的任何testCompile依赖项编译项目A_Test的依赖项。

然后使Project A_Test成为Project B的testCompile依赖项。

从两个项目的作者的角度来看它是不合逻辑的,但我认为当你考虑像junit和scalatest(以及其他项目)这样的项目时,这很有意义。即使这些框架正在测试 - 相关的,它们不被视为自己框架中“测试”目标的一部分 - 它们产生其他项目恰好在其测试配置中使用的主要工件。您只想遵循相同的模式。

尝试做这里列出的其他答案并不适合我个人(使用Gradle 1.9),但我发现我在这里描述的模式无论如何都是一个更清洁的解决方案。

答案 5 :(得分:11)

基于新的testJar(支持的灵敏度依赖性)解决方案可用作gradle插件:

https://github.com/hauner/gradle-plugins/tree/master/jartest

https://plugins.gradle.org/plugin/com.github.hauner.jarTest/1.0

来自文档

  

如果您有多项目gradle构建,则可能需要进行测试   子项目之间的依赖关系(这可能暗示你的   项目结构不合理。)

     

例如,假设项目B所依赖的项目   在项目A和B上不仅具有对A的编译依赖性   也是测试依赖。要编译和运行B的测试,我们需要一些   来自A的测试助手类。

     

默认情况下,gradle不会从测试版本中创建jar工件   项目的输出。

     

此插件添加了testArchives配置(基于testCompile)   和jarTest任务从测试源集创建一个jar(使用   分类器测试添加到jar的名称)。然后我们可以依赖B   A的testArchives配置(也包括   A)的传递依赖性。

     

在A中我们将插件添加到build.gradle:

     

apply plugin: 'com.github.hauner.jarTest'

     

在B中我们参考了   testArchives配置如下:

dependencies {
    ...
    testCompile project (path: ':ProjectA', configuration: 'testArchives') 
}

答案 6 :(得分:8)

请阅读下面的更新。

JustACluelessNewbie描述的类似问题发生在IntelliJ IDEA中。问题是依赖testCompile project(':core').sourceSets.test.output实际上意味着:“依赖于由gradle构建任务生成的类”。因此,如果您打开尚未生成类的干净项目,IDEA将无法识别它们并报告错误。

要解决此问题,您必须在依赖编译类的旁边添加对测试源文件的依赖。

// First dependency is for IDEA
testCompileOnly files { project(':core').sourceSets.test.java.srcDirs }
// Second is for Gradle
testCompile project(':core').sourceSets.test.output

您可以在模块设置 - >中观察IDEA识别的依赖关系。依赖关系(测试范围)

顺便说一下。这不是一个好的解决方案,所以重构值得考虑。 Gradle本身只有包含测试支持类的特殊子项目。见https://docs.gradle.org/current/userguide/test_kit.html

更新2016-06-05 更多我在考虑提议的解决方案,而不是我喜欢它。它几乎没有问题:

  1. 它在IDEA中创建了两个依赖项。一个指向另一个测试来源编译类。 IDEA认可这些依赖关系的顺序至关重要。您可以通过更改模块设置中的依赖顺序来玩它 - >依赖选项卡。
  2. 通过声明这些依赖关系,您不必要地污染依赖关系结构。
  3. 那么什么是更好的解决方案?在我看来,它正在创建新的自定义源集并将共享类放入其中。实际上,Gradle项目的作者通过创建testFixtures源集来实现它。

    要做到这一点,你只需要:

    1. 创建源集并添加必要的配置。检查Gradle项目中使用的此脚本插件:https://github.com/gradle/gradle/blob/v4.0.0/gradle/testFixtures.gradle
    2. 在依赖项目中声明正确的依赖:

      dependencies {
          testCompile project(path: ':module-with-shared-classes', configuration: 'testFixturesUsageCompile')
      }
      
    3. 将Gradle项目导入IDEA,并在导入时使用“为每个源集创建单独的模块”选项。

答案 7 :(得分:6)

当我尝试构建一个Android项目(gradle 2.2.0)时,Fesler的解决方案对我没有用。 所以我必须手动引用所需的类:

android {
    sourceSets {
        androidTest {
            java.srcDir project(':A').file("src/androidTest/java")
        }
        test {
            java.srcDir project(':A').file("src/test/java")
        }
    }
}

答案 8 :(得分:3)

我参加聚会太晚了(现在是Gradle v4.4),但对于发现此问题的其他人来说:

假设:

~/allProjects
|
|-/ProjectA/module-a/src/test/java
|
|-/ProjectB/module-b/src/test/java

转到项目B的build.gradle(该项目需要A的一些测试类)并添加以下内容:

sourceSets {
    String sharedTestDir = "${projectDir}"+'/module-b/src/test/java'
    test {
        java.srcDir sharedTestDir
    }
}

或(假设您的项目名为“ ProjectB”)

sourceSets {
    String sharedTestDir = project(':ProjectB').file("module-b/src/test/java")
    test {
        java.srcDir sharedTestDir
    }
}

Voila!

答案 9 :(得分:3)

为Gradle 6.6.x创建测试罐

我知道有很多消息告诉你,不好,fe:

但这是如此简单,我只是不喜欢在testFixtures文件夹中单独包含通用测试类的想法。

因此在模块A中:

task jarTests(type: Jar, dependsOn: testClasses) {
    classifier = 'tests'
    from sourceSets.test.output
}
configurations {
    tests {
        extendsFrom testRuntime
    }
}
artifacts {
    tests jarTests
}

在模块B中:

testImplementation project(':moduleA')
testImplementation project(path: ':modukeA', configuration: 'tests')

它就可以了!

答案 10 :(得分:2)

其他一些答案以某种方式导致错误 - Gradle没有检测到其他项目的测试类,或者Eclipse项目在导入时具有无效的依赖项。如果有人有同样的问题,我建议你去:

testCompile project(':core')
testCompile files(project(':core').sourceSets.test.output.classesDir)

第一行强制Eclipse将另一个项目链接为依赖项,因此所有源都包含在内并且是最新的。第二个允许Gradle实际查看源,而不会导致任何无效的依赖性错误,如testCompile project(':core').sourceSets.test.output

答案 11 :(得分:2)

如果您需要在测试之间共享模拟依赖项,则可以创建新项目projectA-mock,然后将其作为测试依赖项添加到ProjectAProjectB

dependencies {
  testCompile project(':projectA-mock')
}

这是共享模拟依赖项的明确解决方案,但如果您需要在ProjectA中运行ProjectB中的测试,请使用其他解决方案。

答案 12 :(得分:1)

如果您想使用 artifact 依赖项来拥有:

  • ProjectB的源类取决于Project A的源类
  • ProjectB的测试类取决于Project A的测试类

然后 build.gradle 中ProjectB的依赖项部分应如下所示:

StackTraceElement

为此,ProjectA需要构建一个 -tests jar,并将其包含在它产生的工件中。

ProjectA的 build.gradle 应该包含如下配置:

dependencies {

  compile("com.example:projecta:1.0.0")

  testCompile("com.example:projecta:1.0.0:tests")

}

将ProjectA的工件发布到您的工件时,它们将包含一个-测试 jar。

ProjectB的“依赖项”部分中的 testCompile 将在 -tests jar中引入这些类。


如果要出于开发目的在ProjectB中 includeFlat ProjectA的源类和测试类,则ProjectB的 build.gradle 中的依赖项部分将如下所示:

task testsJar(type: Jar, dependsOn: testClasses) {
    classifier = 'tests'
    from sourceSets.test.output
}

configurations {
    tests
}

artifacts {
    tests testsJar
    archives testsJar
}

jar.finalizedBy(testsJar)

答案 13 :(得分:1)

Nikita提及的 Android + Kotlin 解决方案如下:

task jarTests(type: Jar, dependsOn: "assembleDebugUnitTest") {
    getArchiveClassifier().set('tests')
    from "$buildDir/tmp/kotlin-classes/debugUnitTest"
}

configurations {
    unitTestArtifact
}

artifacts {
    unitTestArtifact jarTests
}

将要使用依赖项的项目的等级:

testImplementation project(path: ':shared', configuration: 'unitTestArtifact')

答案 14 :(得分:-1)

项目B中的

dependencies {
  testCompile project(':projectA').sourceSets.test.output
}

似乎在1.7-rc-2

中工作