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

问题描述 投票:122回答:12

我有一个多项目配置,我想使用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编译测试文件。

build dependencies gradle multi-project
12个回答
109
投票

Deprecated

在Project B中,您只需要添加一个testCompile依赖项:

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

用Gradle 1.7测试。


2
投票

如果您需要在测试之间共享模拟依赖项,则可以创建新项目testCompile project(':core').sourceSets.test.output,然后将其作为测试依赖项添加到projectA-mockProjectA

ProjectB

这是共享模拟依赖项的明确解决方案,但如果您需要在dependencies { testCompile project(':projectA-mock') } 中运行来自ProjectA的测试,请使用其他解决方案。


2
投票

如果要使用工件依赖项来:

  • ProjectB的源类依赖于Project A的源类
  • ProjectB的测试类依赖于Project A的测试类

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

ProjectB

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

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

dependencies {

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

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

}

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

ProjectB的依赖项部分中的testCompile将引入-tests jar中的类。


如果您想在ProjectB中包含Flat 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)

-1
投票

在项目B中:

dependencies {

  compile project(':projecta')

  testCompile project(path: ':projecta', configuration: 'tests')

}

似乎在1.7-rc-2中工作


55
投票

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

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

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

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

configurations {
  testArtifacts
}

artifacts {
   testArtifacts myTestsJar
}

并为Project添加qazxsw poi依赖项

testCompile

17
投票

我知道这是一个老问题,但我遇到了同样的问题,花了一些时间弄清楚发生了什么。我正在使用Gradle 1.9。所有更改都应该在ProjectB的apply plugin: 'java' dependencies { compile project(':ProjectA') testCompile project(path: ':ProjectA', configuration: 'testArtifacts') }

要在Project的测试中使用Project中的测试类:

build.gradle

要确保ProjectA可以使用testCompile files(project(':ProjectA').sourceSets.test.output.classesDir) 属性:

sourceSets

为了确保Project中的测试类实际存在,当您编译Project时:

evaluationDependsOn(':ProjectA')

14
投票

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

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

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

项目A_Test - > src / main / java

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

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

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

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


11
投票

新的基于testJar(支持的trnsitive dependancies)解决方案可用作gradle插件:

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

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

从文档

如果您有一个多项目gradle构建,则可能在子项目之间存在测试依赖关系(这可能暗示您的项目结构不合理)。

例如,假设子项目Project B依赖于项目A和B的项目不仅具有对A的编译依赖性,而且还具有测试依赖性。要编译和运行B的测试,我们需要一些来自A的测试助手类。

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

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

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

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

在B中,我们引用testArchives配置,如下所示:

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

9
投票

请阅读下面的更新。

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

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

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

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

顺便说一句。这不是一个好的解决方案,所以重构值得考虑。 Gradle本身只有包含测试支持类的特殊子项目。见// First dependency is for IDEA testCompileOnly files { project(':core').sourceSets.test.java.srcDirs } // Second is for Gradle testCompile project(':core').sourceSets.test.output

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

  1. 它在IDEA中创建了两个依赖项。一个指向另一个测试来源编译类。 IDEA认可这些依赖关系的顺序至关重要。您可以通过在“模块设置” - >“依赖关系”选项卡中更改依赖关系顺序来使用它。
  2. 通过声明这些依赖关系,您不必要地污染依赖关系结构。

那么什么是更好的解决方案?在我看来,它正在创建新的自定义源集并将共享类放入其中。实际上,Gradle项目的作者通过创建testFixtures源集来实现它。

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

  1. 创建源集并添加必要的配置。检查Gradle项目中使用的此脚本插件:https://docs.gradle.org/current/userguide/test_kit.html
  2. 在依赖项目中声明适当的依赖: https://github.com/gradle/gradle/blob/v4.0.0/gradle/testFixtures.gradle
  3. 将Gradle项目导入到IDEA,并在导入时使用“为每个源集创建单独的模块”选项。

7
投票

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

dependencies {
    testCompile project(path: ':module-with-shared-classes', configuration: 'testFixturesUsageCompile')
}

3
投票

我参加派对的时间太晚了(现在是Gradle v4.4),但对于其他发现这一点的人来说:

假设:

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

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

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

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

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

瞧!


2
投票

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

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

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

© www.soinside.com 2019 - 2024. All rights reserved.