等级测试依赖性

我有两个项目,项目 A 和项目 B 都是用 groovy 编写的,并且使用 gradle 作为它们的构建系统。

项目 A 需要项目 B。 这对于编译代码和测试代码都适用。

如何配置项目 A 的测试类可以访问项目 B 的测试类?

61645 次浏览

You can expose the test classes via a 'tests' configuration and then define a testCompile dependency on that configuration.

I have this block for all java projects, which jars all test code:

task testJar(type: Jar, dependsOn: testClasses) {
baseName = "test-${project.archivesBaseName}"
from sourceSets.test.output
}


configurations {
tests
}


artifacts {
tests testJar
}

Then when I have test code I want to access between projects I use

dependencies {
testCompile project(path: ':aProject', configuration: 'tests')
}

This is for Java; I'm assuming it should work for groovy as well.

The above solution works, but not for the latest version 1.0-rc3 of Gradle.

     task testJar(type: Jar, dependsOn: testClasses) {
baseName = "test-${project.archivesBaseName}"


// in the latest version of Gradle 1.0-rc3
// sourceSets.test.classes no longer works
// It has been replaced with
// sourceSets.test.output


from sourceSets.test.output
}

This works for me (Java)

// use test classes from spring-common as dependency to tests of current module
testCompile files(this.project(':spring-common').sourceSets.test.output)
testCompile files(this.project(':spring-common').sourceSets.test.runtimeClasspath)


// filter dublicated dependency for IDEA export
def isClassesDependency(module) {
(module instanceof org.gradle.plugins.ide.idea.model.ModuleLibrary) && module.classes.iterator()[0].url.toString().contains(rootProject.name)
}


idea {
module {
iml.whenMerged { module ->
module.dependencies.removeAll(module.dependencies.grep{isClassesDependency(it)})
module.dependencies*.exported = true
}
}
}
.....
// and somewhere to include test classes
testRuntime project(":spring-common")

For Gradle 1.5

task testJar(type: Jar, dependsOn: testClasses) {
from sourceSets.test.java
classifier "tests"
}

This is a simpler solution that doesn't require an intermediate jar file:

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

There's more discussion in this question: Multi-project test dependencies with gradle

For Android on the latest gradle version (I'm currently on 2.14.1) you just need to add the below in Project B to get all the test dependencies from Project A.

dependencies {
androidTestComplie project(path: ':ProjectA')
}

If ProjectA contains the test code you wish to use in ProjectB and ProjectB wants to use artifacts to include the test code, then ProjectB's build.gradle would look like this:

dependencies {


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


}

Then you need to add an archives command to the artifacts section in ProjectA's build.gradle:

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


configurations {
tests
}


artifacts {
tests testsJar
archives testsJar
}


jar.finalizedBy(testsJar)

Now when ProjectA's artifacts are published to your artifactory they will include a -tests jar. This -tests jar can then be added as a testCompile dependency for ProjectB (as shown above).

This is now supported as a first class feature in Gradle (since 5.6)

Modules with java or java-library plugins can also include a java-test-fixtures plugin which exposes helper classes and resources to be consumed with testFixtures helper. Benefit of this approach against artifacts and classifiers are:

  • proper dependency management (implementation/api)
  • nice separation from test code (separate source set)
  • no need to filter out test classes to expose only utilities
  • maintained by Gradle

Example:

:modul:one

modul/one/build.gradle

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


dependencies {
testFixturesImplementation("your.jar:dependency:0.0.1")
}

or lazyly just add all dependencies of main implementation configuration:

val testFixturesImplementation by configurations.existing
val implementation by configurations.existing
testFixturesImplementation.get().extendsFrom(implementation.get())

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
}
}

For more info, see the documentation: https://docs.gradle.org/current/userguide/java_testing.html#sec:java_test_fixtures

dependencies {
testImplementation project(':project_name')
}