it-swarm.com.de

Multiprojekt-Testabhängigkeiten mit Gradle

Ich habe eine Konfiguration für mehrere Projekte und möchte gradle verwenden.

Meine Projekte sind so:

  • Projekt A

    • -> src/main/Java
    • -> src/test/Java
  • Projekt B 

    • -> src/main/Java (abhängig von src/main/Java von Projekt A
    • -> src/test/Java (abhängig von src/test/Java von Projekt A

Meine Project B build.gradle-Datei sieht folgendermaßen aus:

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

Die Aufgabe compileJava funktioniert hervorragend, aber die compileTestJava kompiliert die Testdatei nicht aus Project A .

118
mathd

Veraltet

In Project B müssen Sie lediglich eine testCompile-Abhängigkeit hinzufügen:

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

Getestet mit Gradle 1.7.

103
Fesler

Ein einfacher Weg ist das Hinzufügen einer expliziten Aufgabenabhängigkeit in ProjectB:

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

Schwieriger (aber klarer) Weg ist das Erstellen zusätzlicher Artefaktkonfigurationen für ProjectA:

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

configurations {
  testArtifacts
}

artifacts {
   testArtifacts myTestsJar
}

und fügen Sie die testCompile-Abhängigkeit für ProjectB hinzu

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

Ich weiß, es ist eine alte Frage, aber ich hatte nur das gleiche Problem und habe einige Zeit damit verbracht, herauszufinden, was los ist. Ich benutze Gradle 1.9. Alle Änderungen sollten in ProjectBs build.gradle enthalten sein.

So verwenden Sie Testklassen von ProjectA in Tests von ProjectB:

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

So stellen Sie sicher, dass die Eigenschaft sourceSets für ProjectA verfügbar ist:

evaluationDependsOn(':ProjectA')

Um sicherzustellen, dass Testklassen von ProjectA tatsächlich vorhanden sind, wenn Sie ProjectB kompilieren:

compileTestJava.dependsOn tasks.getByPath(':ProjectA:testClasses')
17
Dominik Pawlak

Ich bin in letzter Zeit selbst auf dieses Problem gestoßen, und Mann ist es eine schwierige Aufgabe, Antworten zu finden.

Der Fehler, den Sie machen, ist der Gedanke, dass ein Projekt seine Testelemente auf dieselbe Weise exportieren soll, wie es seine primären Artefakte und Abhängigkeiten exportiert.

Was mir persönlich viel mehr gelingt, war ein neues Projekt in Gradle. In Ihrem Beispiel würde ich es nennen

Projekt A_Test -> src/main/Java

Ich würde die Dateien, die Sie derzeit in Projekt A/src/test/Java haben, in src/main/Java einfügen. Machen Sie testCompile-Abhängigkeiten Ihres Projekts. A Kompilieren Sie Abhängigkeiten von Project A_Test.

Machen Sie dann Project A_Test zu einer testCompile-Abhängigkeit von Project B.

Es ist nicht logisch, wenn Sie aus der Sicht des Autors beider Projekte darauf ankommen, aber ich denke, es macht viel Sinn, wenn Sie an Projekte wie junit und scalatest (und andere) denken. Auch wenn diese Frameworks auf Tests bezogen sind werden nicht als Teil der "Test" -Ziele innerhalb ihrer eigenen Rahmenbedingungen betrachtet - sie erzeugen primäre Artefakte, die andere Projekte in ihrer Testkonfiguration verwenden. Sie möchten nur diesem Muster folgen.

Der Versuch, die anderen hier aufgelisteten Antworten zu beantworten, hat für mich persönlich nicht funktioniert (mit Gradle 1.9), aber ich habe festgestellt, dass das hier beschriebene Muster ohnehin eine sauberere Lösung ist.

13
Martin Snyder

Neue testJar-basierte (trnsitive abhängigkeit unterstützt) lösung als gradle plugin verfügbar:

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

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

Aus der Dokumentation

Falls Sie einen Gradle-Build für mehrere Projekte haben, haben Sie möglicherweise test Abhängigkeiten zwischen Unterprojekten (was wahrscheinlich darauf hindeutet, dass Ihre -Projekte nicht gut strukturiert sind).

Nehmen Sie beispielsweise an, dass ein Projekt von dem Unterprojekt Projekt B abhängig ist in Projekt A und B hat nicht nur eine Kompilierabhängigkeit von A, sondern auch eine Testabhängigkeit. Um die Tests von B zu kompilieren und auszuführen, benötigen wir einige Testhelferklassen von A.

Standardmäßig erstellt Gradle aus dem Testaufbau kein Jar-Artefakt Ausgabe eines Projekts.

Dieses Plugin fügt eine testArchives-Konfiguration hinzu (basierend auf testCompile) und eine jarTest-Task zum Erstellen einer jar aus dem Testquellensatz (wobei der -klassifizierertest zum Namen der jar hinzugefügt wird). Wir können uns dann in B auf .__ verlassen. Die testArchives-Konfiguration von A (die auch die transitiven Abhängigkeiten von A enthält.).

In A würden wir das Plugin zu build.gradle hinzufügen:

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

In B verweisen wir auf das testArchives Konfiguration wie folgt:

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

Bitte lesen Sie das Update unten.

Ähnliche Probleme, die von JustACluelessNewbie beschrieben werden, treten bei IntelliJ IDEA auf. Das Problem ist, dass die Abhängigkeit testCompile project(':core').sourceSets.test.output tatsächlich bedeutet: "hängen Sie von Klassen ab, die von der Gradle-Build-Task generiert werden". Wenn Sie also ein sauberes Projekt öffnen, in dem noch keine Klassen erstellt wurden, erkennt IDEA diese nicht und meldet Fehler.

Um dieses Problem zu beheben, müssen Sie neben der Abhängigkeit von kompilierten Klassen eine Abhängigkeit von Testquelldateien hinzufügen.

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

Sie können die von IDEA erkannten Abhängigkeiten in Moduleinstellungen -> Abhängigkeiten (Testumfang) beobachten.

Übrigens Dies ist keine schöne Lösung von Nizza, also ist Refactoring eine Überlegung wert. Gradle selbst verfügt über ein spezielles Teilprojekt, das nur Testunterstützungsklassen enthält. Siehe https://docs.gradle.org/current/userguide/test_kit.html

Update 2016-06-05 Mehr Ich denke über Lösungsvorschläge nach, weniger gefällt mir. Es gibt wenige Probleme damit:

  1. Es erstellt zwei Abhängigkeiten in IDEA. Eine verweist auf die Testquellen, eine andere auf die kompilierten Klassen. Es ist entscheidend, in welcher Reihenfolge diese Abhängigkeiten von IDEA erkannt werden. Sie können damit spielen, indem Sie die Reihenfolge der Abhängigkeiten in den Moduleinstellungen -> Registerkarte Abhängigkeiten ändern.
  2. Durch die Deklaration dieser Abhängigkeiten verschmutzen Sie die Abhängigkeitsstruktur unnötig.

Also, was ist die bessere Lösung? Meiner Meinung nach werden neue benutzerdefinierte Quellensätze erstellt und gemeinsam genutzte Klassen eingefügt. Eigentlich haben die Autoren des Gradle-Projekts den Quellsatz von testFixtures erstellt.

Dazu müssen Sie nur:

  1. Erstellen Sie einen Quellsatz und fügen Sie die erforderlichen Konfigurationen hinzu. Überprüfen Sie dieses in Gradle-Projekt verwendete Skript-Plugin: https://github.com/gradle/gradle/blob/v4.0.0/gradle/testFixtures.gradle
  2. Deklarieren Sie die richtige Abhängigkeit im abhängigen Projekt:

    dependencies {
        testCompile project(path: ':module-with-shared-classes', configuration: 'testFixturesUsageCompile')
    }
    
  3. Importieren Sie das Gradle-Projekt nach IDEA und verwenden Sie beim Importieren die Option "Separates Modul pro Quellsatz erstellen".
8
Václav Kužel

Die Fesler-Lösung hat für mich nicht funktioniert, als ich versuche, ein Android-Projekt (Gradle 2.2.0) zu erstellen.

Android {
    sourceSets {
        androidTest {
            Java.srcDir project(':A').file("src/androidTest/Java")
        }
        test {
            Java.srcDir project(':A').file("src/test/Java")
        }
    }
}
5
Beloo

Ich bin so spät auf der Party (es ist jetzt Gradle v4.4), aber für alle anderen, die dies finden:

Gehen Sie zum build.gradle von Projekt B (dem, das einige Testklassen von A benötigt) und fügen Sie Folgendes hinzu:

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

Voila!

2
tricknology

Wenn Sie Scheinabhängigkeiten haben, die Sie zwischen den Tests gemeinsam nutzen müssen, können Sie das neue Projekt projectA-mock erstellen und es als Testabhängigkeit zu ProjectA und ProjectB hinzufügen:

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

Dies ist eine klare Lösung, um scheinbare Abhängigkeiten gemeinsam zu nutzen. Wenn Sie jedoch Tests von ProjectA in ProjectB ausführen müssen, verwenden Sie eine andere Lösung.

1
sylwano

Einige der anderen Antworten führten auf die eine oder andere Weise zu Fehlern - Gradle erkannte keine Testklassen aus anderen Projekten oder das Eclipse-Projekt wies beim Import ungültige Abhängigkeiten auf. Wenn jemand das gleiche Problem hat, schlage ich vor:

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

Die erste Zeile zwingt Eclipse, das andere Projekt als Abhängigkeit zu verknüpfen, sodass alle Quellen einbezogen werden und auf dem neuesten Stand sind. Die zweite ermöglicht Gradle, die Quellen tatsächlich zu sehen, ohne jedoch ungültige Abhängigkeitsfehler wie testCompile project(':core').sourceSets.test.output zu verursachen.

1

Wenn Sie Artifact Abhängigkeiten verwenden möchten, haben Sie:

  • Die Quellklassen von ProjectB hängen von den Quellklassen von Project A ab
  • Die Testklassen von ProjectB hängen von den Testklassen von Project A ab

dann sollte der Abschnitt der Abhängigkeiten von ProjectB in build.gradle so aussehen:

dependencies {

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

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

}

Damit dies funktioniert, muss ProjectA einen -test jar erstellen und in die von ihm erzeugten Artefakte einschließen. 

ProjectAs build.gradle sollte folgende Konfiguration enthalten:

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

configurations {
    tests
}

artifacts {
    tests testsJar
    archives testsJar
}

jar.finalizedBy(testsJar)

Wenn ProjectA-Artefakte in Ihrem Artefakt veröffentlicht werden, enthalten sie ein -tests jar.

Der testCompile in ProjectBs Abhängigkeitsbereich wird die Klassen in/tests jar einbringen.


Wenn Sie includeFlat ProjectAs Quell- und Testklassen in ProjectB zu Entwicklungszwecken verwenden möchten, würde der Abschnitt Abhängigkeiten in ProjectBs build.gradle folgendermaßen aussehen:

dependencies {

  compile project(':projecta')

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

}
1
Joman68