web-dev-qa-db-fra.com

Dépendances de test multi-projets avec gradle

J'ai une configuration multi-projet et je veux utiliser gradle.

Mes projets sont comme ça:

  • Projet A

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

    • -> src/main/Java (dépend de src/main/Java sur Projet A
    • -> src/test/Java (dépend de src/test/Java sur Projet A

Le fichier/ Projet B build.gradle ressemble à ceci:

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

La tâche compileJava fonctionne très bien mais la compileTestJava ne compile pas le fichier de test à partir de Projet A .

118
mathd

Obsolète

Dans Projet B , il vous suffit d'ajouter une dépendance testCompile:

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

Testé avec Gradle 1.7.

103
Fesler

Une méthode simple consiste à ajouter une dépendance explicite à la tâche dans ProjectB:

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

Une manière difficile (mais plus claire) est de créer une configuration d'artefact supplémentaire pour ProjectA:

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

configurations {
  testArtifacts
}

artifacts {
   testArtifacts myTestsJar
}

et ajoutez la dépendance testCompile pour ProjectB

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

Je sais que c’est une vieille question mais j’ai eu le même problème et j’ai passé du temps à comprendre ce qui se passait. J'utilise Gradle 1.9. Toutes les modifications doivent être dans build.gradle de ProjectB

Pour utiliser les classes de test de ProjectA dans les tests de ProjectB:

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

Pour vous assurer que la propriété sourceSets est disponible pour ProjectA:

evaluationDependsOn(':ProjectA')

Pour vous assurer que les classes de test de ProjectA sont bien présentes, lorsque vous compilez ProjectB:

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

J'ai moi-même rencontré ce problème récemment, et l'homme est un problème difficile à résoudre.

L'erreur que vous faites est de penser qu'un projet doit exporter ses éléments de test de la même manière qu'il exporte ses artefacts principaux et ses dépendances.

Personnellement, j’ai eu beaucoup plus de succès lors de la création d’un nouveau projet à Gradle. Dans votre exemple, je l'appellerais

Projet A_Test -> src/main/Java

Je mettrais dans src/main/Java les fichiers que vous avez actuellement dans le projet A/src/test/Java. Faites des dépendances testCompile de votre projet A des dépendances de compilation du projet A_Test.

Faites ensuite du projet A_Test une dépendance testCompile du projet B.

Ce n’est pas logique lorsque vous abordez la question du point de vue de l’auteur des deux projets, mais je pense que cela a beaucoup de sens de penser à des projets comme Junit et Scalatest (et d’autres. Même si ces frameworks sont liés aux tests, ils ne sont pas considérés comme faisant partie des cibles de "test" dans leurs propres cadres - ils produisent des artefacts primaires que d'autres projets utilisent simplement dans leur configuration de test. Vous souhaitez simplement suivre le même schéma.

Essayer de faire les autres réponses énumérées ici ne fonctionnait pas pour moi personnellement (avec Gradle 1.9), mais j’ai trouvé que le motif que je décris ici est de toute façon une solution plus propre.

13
Martin Snyder

Nouvelle solution basée sur testJar (dépendances trnsitives prises en charge) disponible en tant que plugin Gradle:

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

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

De la documentation

Si vous avez une construction multi-projets, vous pouvez avoir un test dépendances entre sous-projets (ce qui est probablement un indice que vos projets ne sont pas bien structurés).

Par exemple, supposons un projet dont le sous-projet Projet B dépend sur les projets A et B n’a pas seulement une dépendance de compilation sur A mais aussi une dépendance de test. Pour compiler et exécuter les tests de B, nous avons besoin de test des classes d'assistance de A.

Par défaut, gradle ne crée pas d'artefact jar à partir de la version de test sortie d'un projet.

Ce plugin ajoute une configuration testArchives (basée sur testCompile) et une tâche jarTest pour créer un fichier JAR à partir du jeu de sources de test (avec le test du classificateur .__ ajouté au nom du fichier JAR). Nous pouvons alors compter sur B sur la configuration testArchives de A (qui inclura également les dépendances transitive de A).

En A, nous ajouterions le plugin à build.gradle:

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

En B, nous référons le Configuration de testArchives comme ceci:

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

Veuillez lire la mise à jour ci-dessous.

Des problèmes similaires décrits par JustACluelessNewbie se produisent dans IntelliJ IDEA. Le problème est que dépendance testCompile project(':core').sourceSets.test.output signifie en réalité: "dépend des classes générées par la tâche de construction de niveaux". Ainsi, si vous ouvrez un projet propre dans lequel les classes ne sont pas encore générées, IDEA ne les reconnaîtra pas et signalera une erreur.

Pour résoudre ce problème, vous devez ajouter une dépendance sur les fichiers source de test à côté de la dépendance sur les classes compilées.

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

Vous pouvez observer les dépendances reconnues par IDEA dans Paramètres du module -> Dépendances (portée de test)}.

Btw. Ce n'est pas une bonne solution, le refactoring vaut donc la peine d'être envisagé. Gradle lui-même a un sous-projet spécial contenant uniquement des classes de support de test. Voir https://docs.gradle.org/current/userguide/test_kit.html

Mise à jour 2016-06-05 Plus Je pense à la solution proposée, moins je l’aime. Cela pose quelques problèmes:

  1. Cela crée deux dépendances dans IDEA. Un point pour tester les sources, un autre pour les classes compilées. Et il est crucial dans quel ordre ces dépendances sont reconnues par IDEA. Vous pouvez y jouer en modifiant l’ordre de dépendance dans les paramètres du module -> onglet Dépendances.
  2. En déclarant ces dépendances, vous polluez inutilement la structure de dépendance.

Alors, quelle est la meilleure solution? À mon avis, cela crée un nouvel ensemble de sources personnalisé et y ajoute des classes partagées. En réalité, les auteurs du projet Gradle l'ont fait en créant le jeu de sources testFixtures.

Pour le faire, il vous suffit de:

  1. Créez un ensemble source et ajoutez les configurations nécessaires. Vérifiez ce plug-in de script utilisé dans le projet Gradle: https://github.com/gradle/gradle/blob/v4.0.0/gradle/testFixtures.gradle
  2. Déclarez la dépendance appropriée dans le projet dépendant:

    dependencies {
        testCompile project(path: ':module-with-shared-classes', configuration: 'testFixturesUsageCompile')
    }
    
  3. Importez le projet Gradle dans IDEA et utilisez l'option "créer un module séparé par ensemble de sources" lors de l'importation.
8
Václav Kužel

La solution de Fesler n'a pas fonctionné pour moi, lorsque j'ai essayé de construire un projet Android (version 2.2.0) . Je devais donc référencer manuellement les classes requises:

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

Je suis si tard pour la fête (c'est maintenant Gradle v4.4) mais pour tous ceux qui trouvent ça:

Accédez au build.gradle du projet B (celui qui nécessite des classes de test de A) et ajoutez ce qui suit:

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

Voila!

2
tricknology

Si vous devez partager des dépendances factices entre les tests, vous pouvez créer un nouveau projet projectA-mock, puis l'ajouter en tant que dépendance de test à ProjectA et ProjectB:

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

Ceci est une solution claire pour partager des dépendances factices, mais si vous devez exécuter des tests à partir de ProjectA dans ProjectB, utilisez une autre solution.

1
sylwano

Certaines des autres réponses ont entraîné des erreurs d'une manière ou d'une autre - Gradle n'a pas détecté de classes de test provenant d'autres projets ou le projet Eclipse avait des dépendances non valides lors de l'importation. Si quelqu'un a le même problème, je suggère d'aller avec:

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

La première ligne oblige Eclipse à associer l’autre projet en tant que dépendance, afin que toutes les sources soient incluses et à jour. La seconde permet à Gradle de voir réellement les sources, sans causer d’erreurs de dépendance non valides comme le fait testCompile project(':core').sourceSets.test.output.

1

Si vous voulez utiliser les dépendances artifact pour avoir:

  • Les classes sources de ProjectB dépendent des classes sources du projet A
  • Les classes de test de ProjectB dépendent des classes de test du projet A

alors la section des dépendances de ProjectB dans build.gradle devrait ressembler à ceci:

dependencies {

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

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

}

Pour que cela fonctionne, ProjectA doit créer un fichier jar -tests et l'inclure dans les artefacts qu'il produit. 

Le projet build.gradle de ProjectA devrait contenir la configuration suivante:

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

configurations {
    tests
}

artifacts {
    tests testsJar
    archives testsJar
}

jar.finalizedBy(testsJar)

Lorsque les artefacts de ProjectA sont publiés sur votre artefact, ils incluent un fichier jar -tests.

TestCompile dans la section des dépendances de ProjectB importera les classes du fichier jar -tests.


Si vous voulez includeFlat les classes source et de test de ProjectA dans ProjectB à des fins de développement, la section des dépendances dans build.gradle de ProjectB ressemblerait à ceci:

dependencies {

  compile project(':projecta')

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

}
1
Joman68