首页 文章

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

提问于
浏览
119

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

我的项目是这样的:

  • 项目A.

    • src/main/java

    • src/test/java

  • 项目B.

    • src/main/java (取决于 src/main/java Project A

    • src/test/java (取决于 src/test/javaProject A

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

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

任务 compileJava 工作得很好,但 compileTestJava 没有从 Project A 编译测试文件 .

12 回答

  • 50

    已弃用

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

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

    用Gradle 1.7测试 .

  • 103

    简单的方法是在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')
    }
    
  • -1

    我知道's an old question but I just had the same problem and spent some time figuring out what is going on. I'm使用Gradle 1.9 . 所有更改都应该在ProjectB的 build.gradle

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

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

    要确保 sourceSets 属性可用于ProjectA:

    evaluationDependsOn(':ProjectA')
    

    为了确保ProjectA中的测试类实际存在,在编译ProjectB时:

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

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

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

    我个人在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),但我发现我在这里描述的模式无论如何都是一个更清洁的解决方案 .

  • 1

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

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

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

    从文档

    如果您有一个多项目gradle构建,则可能在子项目之间存在测试依赖关系(这可能暗示您的项目结构不合理) . 例如,假设子项目Project B依赖于项目A和B的项目不仅具有对A的编译依赖性,而且还具有测试依赖性 . 要编译和运行B的测试,我们需要一些来自A的测试助手类 . 默认情况下,gradle不会从项目的测试构建输出中创建jar工件 . 此插件添加了testArchives配置(基于testCompile)和jarTest任务,以从测试源集创建jar(将分类器测试添加到jar的名称) . 然后我们可以在B的testArchives配置中依赖于B(它还将包括A的传递依赖性) . 在A中我们将插件添加到build.gradle:apply plugin:'com.github.hauner.jarTest'在B中我们引用testArchives配置,如下所示:

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

    请阅读下面的更新 .

    JustACluelessNewbie描述的类似问题发生在IntelliJ IDEA中 . 问题是依赖 testCompile project(':core').sourceSets.test.output 实际上意味着:"depend on classes generated by gradle build task" . 因此,如果您打开尚未生成类的干净项目,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

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

    • 它在IDEA中创建了两个依赖项 . 一指向另一个编译类的源代码 . IDEA认可这些依赖关系的顺序至关重要 . 您可以通过在“模块设置” - >“依赖关系”选项卡中更改依赖关系顺序来使用它 .

    • 通过声明这些依赖关系,您不必要地污染依赖关系结构 .

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

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

    dependencies {
        testCompile project(path: ':module-with-shared-classes', configuration: 'testFixturesUsageCompile')
    }
    
    • 将Gradle项目导入IDEA并在导入时使用"create separate module per source set"选项 .
  • 5

    当我尝试构建一个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")
            }
        }
    }
    
  • 1

    我参加派对的时间太晚了(现在是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
        }
    }
    

    瞧!

  • 8

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

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

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

  • 13

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

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

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

  • 17

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

    • ProjectB 's source classes depend on Project A'的源类

    • ProjectB 's test classes depend on Project A'的测试类

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

    dependencies {
    
      compile("com.example:projecta:1.0.0")
    
      testCompile("com.example:projecta:1.0.0:tests")
    
    }
    

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

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

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

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

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


    如果你想includeFlat ProjectA 's source and test classes in ProjectB for development purposes then the dependencies section in ProjectB',build.gradle将如下所示:

    dependencies {
    
      compile project(':projecta')
    
      testCompile project(path: ':projecta', configuration: 'tests')
    
    }
    
  • 2

    在项目B中:

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

    似乎在1.7-rc-2中工作

相关问题