gradle을 사용한 다중 프로젝트 테스트 종속성


153

다중 프로젝트 구성이 있고 gradle을 사용하고 싶습니다.

내 프로젝트는 다음과 같습니다

  • 프로젝트 A

    • -> src/main/java
    • -> src/test/java
  • 프로젝트 B

    • -> src/main/java( 프로젝트 Asrc/main/java 에 따라 다름 )
    • -> src/test/java( 프로젝트 Asrc/test/java 에 따라 다름 )

프로젝트 B build.gradle 파일은 다음과 같습니다.

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

작업 compileJava은 훌륭하지만 프로젝트 AcompileTestJava 의 테스트 파일을 컴파일하지는 않습니다 .


답변:


122

더 이상 사용되지 않음-Gradle 5.6 이상에서는 이 답변을 사용 하십시오 .

프로젝트 B 에서는 testCompile종속성 을 추가하기 만하면됩니다 .

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

Gradle 1.7로 테스트되었습니다.


7
클래스 속성이 더 이상 사용되지 않는 것으로 나타났습니다. 대신 출력을 사용하십시오.
Fesler

12
sourceSets는 더 이상 프로젝트의 공용 속성이 아니므로 Gradle 1.3에서는 작동하지 않습니다.
David Pärsson

3
위의 솔루션은 gradle testClasses빌드 구조가 실제로 유효하기 전에 적어도 하나는 필요하다는 것을 명심하십시오 . 예를 들어 Eclipse 플러그인을 사용하면 그 전에 프로젝트를 가져올 수 없습니다. 정말 부끄러운 일 testCompile project(':A')이 아닙니다. @ DavidPärsson : Fesler가 Gradle 1.7로 테스트 한 이후 "Gradle 1.3"은 "더 이상"모순됩니다.
Patrick Bergner

3
나를 위해 작동하지 않았다. 순환 종속성 실패 : compileTestJava \ --- : testClasses \ --- : compileTestJava (*)
rahulmohan

8
이 작업을 수행하지 마십시오. 프로젝트는 다른 프로젝트에 도달해서는 안됩니다. 대신 Nikita의 답변을 사용하여 이것을 프로젝트 종속성으로 올바르게 모델링하십시오.
Stefan Oehme 17

63

간단한 방법은 ProjectB에 명시적인 작업 종속성을 추가하는 것입니다.

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

어려운 (그러나 더 명확한) 방법은 ProjectA에 대한 추가 아티팩트 구성을 작성하는 것입니다.

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

configurations {
  testArtifacts
}

artifacts {
   testArtifacts myTestsJar
}

testCompileProjectB 에 대한 종속성을 추가하십시오.

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

3
나는 이것을 시도했지만 (간단한 방법) 그것이 testClasses를 빌드하는지 확인하는 동안 CLASSPATH에 테스트 경로를 추가하지 않으므로 ProjectA 테스트 클래스에 의존하는 ProjectB 테스트는 여전히 빌드에 실패합니다.
pjz

1
@dmoebius 다음 testArtifacts과 같은 구성 을 추가해야 합니다. configurations { testArtifacts } 자세한 내용은 Gradle 도움말의이 섹션을 참조하십시오 : gradle.org/docs/current/dsl/…
Nikita Skvortsov

7
Gradle 1.8에서는 답을 원할 from sourceSets.test.output수도 classifier = 'tests'있고 대신 할 수도 있습니다.// pack whatever you need...
Peter Lamberg

1
@PeterLamberg와 함께 전체 솔루션을 사용하는 Gradle 1.12에서 추가가 예상대로 작동 함을 확인했습니다. Eclipse로 프로젝트를 가져 오는 데 영향을 미치지 않습니다.
14:22에 맞습니다

3
이것은 Gradle 4.7에서 작동합니다. 그들은 지금 docs.gradle.org/current/dsl/에
Nathan Williams

19

이것은 이제 Gradle의 최고급 기능으로 지원됩니다.플러그인 이 java있거나 java-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

모듈 / 기타 /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


그들은 Android에서이를 지원하기 위해 노력하고 있습니다. issuetracker.google.com/issues/139762443issuetracker.google.com/issues/139438142
Albert Vila Calvo

18

나는 최근 에이 문제를 직접 겪었으며 사람은 이것이 답을 찾기가 어려운 문제라는 것입니다.

실수는 프로젝트가 기본 아티팩트 및 종속성을 내보내는 것과 같은 방식으로 테스트 요소를 내 보내야한다는 생각입니다.

개인적으로 더 많은 성공을 거둔 것은 Gradle에서 새 프로젝트를 만드는 것이 었습니다. 당신의 예에서, 나는 그것을 이름을 지정할 것입니다

프로젝트 A_Test-> src / main / java

현재 프로젝트 A / src / test / java에있는 파일을 src / main / java에 넣을 것입니다. 프로젝트 A의 모든 테스트 컴파일 종속성을 작성하십시오. 프로젝트 A_Test의 컴파일 종속성.

그런 다음 프로젝트 A_Test를 프로젝트 B의 testCompile 종속성으로 만듭니다.

두 프로젝트의 저자 관점에서 볼 때 논리적이지 않지만 junit 및 scalatest (및 다른 프로젝트와 같은 프로젝트에 대해 생각할 때 많은 의미가 있다고 생각합니다.이 프레임 워크는 테스트와 관련이 있지만) 자체 프레임 워크 내에서 "테스트"대상의 일부로 간주되지 않습니다. 다른 프로젝트가 테스트 구성 내에서 사용하게되는 주요 아티팩트를 생성합니다.

여기에 나열된 다른 답변을 시도해도 개인적으로 효과가 없었지만 (Gradle 1.9 사용) 여기서 설명하는 패턴이 더 깨끗한 솔루션이라는 것을 알았습니다.


예, 하루가 끝날 때이 접근 방식을 선택했습니다.
koma

이것이 가장 좋은 방법입니다! 프로젝트 A에서 테스트 코드를 유지하고 A src / test / java 및 B src / test / java에 대한 종속성 만 A_Test로 이동하는 것을 제외하고. 그런 다음 프로젝트 A_Test 모두의 testImplementation 의존하고 B.
에릭 Sillén

17

나는 그것이 오래된 질문이라는 것을 알고 있지만 방금 같은 문제가 있었고 무슨 일이 일어나고 있는지 알아내는 데 시간을 보냈습니다. Gradle 1.9를 사용하고 있습니다. 모든 변경 사항은 ProjectB에 있어야합니다.build.gradle

ProjectB 테스트에서 ProjectA의 테스트 클래스를 사용하려면

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

sourceSetsProjectA에서 속성을 사용할 수 있도록하려면 :

evaluationDependsOn(':ProjectA')

ProjectB를 컴파일 할 때 ProjectA의 테스트 클래스가 실제로 있는지 확인하려면 다음을 수행하십시오.

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

1
이것은 내가 생략 해야하는 것을 제외하고는 나를 위해 일했습니다 .classesDir.

11

gradle 플러그인으로 제공되는 새로운 testJar 기반 (트랜스 티브 의존성 지원) 솔루션 :

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

1
이 링크가 질문에 대한 답변을 제공 할 수 있지만 여기에 답변의 필수 부분을 포함시키고 참조 용 링크를 제공하는 것이 좋습니다. 링크 된 페이지가 변경되면 링크 전용 답변이 유효하지 않을 수 있습니다. - 검토에서
Ian

몇 줄의 텍스트가 추가되었습니다
demon101

어쨌든, 새로운 gradle 플러그인에 대한 정보가 제공되었습니다.
demon101

4
@ demon101 Gradle을 4.6에서 작동하지 않는, 점점 오류Could not get unknown property 'testClasses' for project ':core' of type org.gradle.api.Project.
인 Vignesh 다르

11

다음 업데이트를 읽으십시오.

JustACluelessNewbie가 설명한 비슷한 문제가 IntelliJ IDEA에서 발생합니다. 문제는 그 의존성testCompile project(':core').sourceSets.test.output 실제로 "그라들 빌드 작업에 의해 생성 된 클래스에 따라"라는 것을 의미한다는 것입니다. 따라서 클래스가 생성되지 않은 깨끗한 프로젝트를 열면 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가 인식 한 종속성을 관찰 할 수 있습니다. .

Btw. 이것은 좋은 해결책이 아니므로 리팩토링을 고려해 볼 가치가 있습니다. Gradle 자체에는 테스트 지원 클래스 만 포함하는 특수 하위 프로젝트가 있습니다. https://docs.gradle.org/current/userguide/test_kit.html을 참조 하십시오

2016-06-05 업데이트 더 제안 된 솔루션에 대해 생각하고 있습니다. 그것에 대한 몇 가지 문제가 있습니다 :

  1. IDEA에는 두 가지 종속성이 있습니다. 하나는 컴파일 된 클래스에 대한 다른 소스를 테스트하는 것입니다. 그리고 이러한 의존성을 IDEA가 인식하는 순서가 중요합니다. 모듈 설정-> 종속성 탭에서 종속성 순서를 변경하여 재생할 수 있습니다.
  2. 이러한 의존성을 선언함으로써 불필요하게 오염 구조를 오염시킬 수 있습니다.

더 나은 해결책은 무엇입니까? 제 생각에는 새로운 커스텀 소스 세트를 만들고 공유 클래스를 넣습니다. 실제로 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로 가져오고 가져 오는 동안 "소스 세트마다 별도의 모듈 작성"옵션을 사용하십시오.


1
@jannis가 수정되었습니다. Btw. Gradle을 그 그루비 기반의 테스트 설비가 새로운 코 틀린에 플러그인 이동 기반 : github.com/gradle/gradle/blob/v5.0.0/buildSrc/subprojects/...
바츨라프 Kužel

@ VáclavKužel 귀하의 블로그 게시물을 통해 흥미로운 솔루션을 찾았으며 내 문제를 매우 잘 해결했습니다. 감사합니다;)
zaerymoghaddam

10

Fesler의 솔루션은 안드로이드 프로젝트 (gradle 2.2.0)를 빌드하려고 시도했을 때 저에게 효과적이지 않았습니다. 그래서 필요한 클래스를 수동으로 참조해야했습니다.

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

1
프로젝트 ( ': A') 뒤에 작은 따옴표가 누락되었습니다. m8
Ryan Newsom 님이

1
안드로이드를 들어이 아이디어는 해키 느낌없이, 나를 위해 아름답게 일 stackoverflow.com/a/50869037/197141
arberg

@arberg 예, 좋은 접근 방식으로 보입니다. 내가 보는 유일한 제한은 @VisibleForTesting보푸라기 규칙입니다. 테스트 폴더가 아닌 일반 모듈에서는 이러한 메소드를 호출 할 수 없습니다.
벨루

5

나는 파티에 너무 늦었습니다 (현재 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
    }
}

짜잔!


3
이 질문에는 Android가 언급되어 있지 않습니다. 개발자가 Android 용으로 개발 중인지 아니면 Android 개발자 전용인지에 대한 대답을 무시할 수 있습니까?
Robin Green

4

당신은 당신이 검사 사이에 공유 할 필요가 모의 종속성이있는 경우에, 당신은 새 프로젝트를 만들 수 있습니다 projectA-mock다음 테스트 종속성에 추가 ProjectA하고 ProjectB:

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

모의 종속성을 공유하는 명확한 솔루션이지만 다른 솔루션 ProjectAProjectB사용하여 테스트를 실행해야하는 경우 .


공유 모의 케이스를위한 훌륭한 솔루션!
Erik Sillén

4

이슈 종속성을 사용 하려면 다음을 수행하십시오.

  • ProjectB의 소스 클래스는 프로젝트 A의 소스 클래스에 따라 다릅니다.
  • ProjectB의 테스트 클래스는 프로젝트 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 이 포함됩니다 .

testCompile ProjectB의 종속 섹션은의 클래스에 나타납니다 -tests 항아리.


당신이 원하는 경우 includeFlat 개발 목적 ProjectB에 PROJECTA의 소스와 테스트 클래스 다음은 ProjectB의 섹션 종속 build.gradle은 다음과 같을 것이다 :

dependencies {

  compile project(':projecta')

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

}

1
불행히도 (Gradle 6에서는) 더 이상 구성 '테스트'가 없기 때문에 정확히 내가 원하는 것 인 플랫 포함이 더 이상 작동하지 않습니다. println(configurations.joinToString("\n") { it.name + " - " + it.allDependencies.joinToString() })(kotlin 빌드 스크립트에서) 사용하여 어떤 구성이 여전히 존재하고 종속성이 있는지 확인했지만 이러한 모든 Gradle에 대해 다음과 같이 불평했습니다.Selected configuration 'testCompileClasspath' on 'project :sdk' but it can't be used as a project dependency because it isn't intended for consumption by other components.
Xerus

2

다른 답변 중 일부는 어떤 방식 으로든 오류를 일으켰습니다. Gradle이 다른 프로젝트에서 테스트 클래스를 감지하지 못했거나 Eclipse 프로젝트를 가져올 때 유효하지 않은 종속성이있었습니다. 누구든지 같은 문제가 발생하면 다음을 수행하는 것이 좋습니다.

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

첫 번째 행은 Eclipse가 다른 프로젝트를 종속성으로 링크하도록하여 모든 소스가 포함되어 있고 최신 상태입니다. 두 번째는 Gradle이 실제로 소스를 볼 수있게하는 것과 같이 잘못된 종속성 오류를 발생 testCompile project(':core').sourceSets.test.output시키지 않습니다.


2

Kotlin DSL을 사용하는 경우 Gradle 에 따라 이와 같은 작업을 만들어야합니다. 설명서 .

이전 답변과 마찬가지로 테스트 클래스를 공유하는 프로젝트 내에 특수 구성을 작성하여 테스트 클래스와 기본 클래스를 혼합하지 않아야합니다.

간단한 단계

  1. 프로젝트 A 에서는 다음 을 추가해야합니다 build.gradle.kts.
configurations {
    create("test")
}

tasks.register<Jar>("testArchive") {
    archiveBaseName.set("ProjectA-test")
    from(project.the<SourceSetContainer>()["test"].output)
}

artifacts {
    add("test", tasks["testArchive"])
}
  1. 그런 다음 종속성 의 프로젝트 B 에서 다음 을 추가해야합니다 build.gradle.kts.
dependencies {
    implementation(project(":ProjectA"))
    testImplementation(project(":ProjectA", "test"))
}

-1

프로젝트 B에서 :

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

1.7-rc-2에서 작동하는 것 같습니다


2
또한 Eclipse에서 프로젝트를 처리 할 때 불필요한 복잡성을 초래합니다. @NikitaSkvortsov가 제안한 솔루션이 바람직합니다.
14:22에 맞습니다
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.