Come aggiungo un nuovo set di sorgenti a Gradle?


99

Voglio aggiungere test di integrazione alla mia build Gradle (versione 1.0). Dovrebbero essere eseguiti separatamente dai miei normali test perché richiedono una webapp da distribuire su localhost (testano quella webapp). I test dovrebbero essere in grado di utilizzare le classi definite nel mio set di sorgenti principale. Come posso farlo accadere?

Risposte:


114

Mi ci è voluto un po 'per capirlo e le risorse online non erano eccezionali. Quindi ho voluto documentare la mia soluzione.

Questo è un semplice script di build gradle che ha un set di sorgenti intTest oltre ai set di sorgenti principale e di test:

apply plugin: "java"

sourceSets {
    // Note that just declaring this sourceset creates two configurations.
    intTest {
        java {
            compileClasspath += main.output
            runtimeClasspath += main.output
        }
    }
}

configurations {
    intTestCompile.extendsFrom testCompile
    intTestRuntime.extendsFrom testRuntime
}

task intTest(type:Test){
    description = "Run integration tests (located in src/intTest/...)."
    testClassesDir = project.sourceSets.intTest.output.classesDir
    classpath = project.sourceSets.intTest.runtimeClasspath
}

7
Dovrai comunque dichiarare e configurare un'attività di test di integrazione. In termini di documentazione, c'è un java/withIntegrationTestsesempio nella distribuzione completa di Gradle.
Peter Niederwieser

Grazie @PeterNiederwieser ho corretto il mio script di build di esempio.
Spina

2
Stavo cercando di fare anche questo ... grazie mille per aver pubblicato la soluzione :)
Igor Popov

@PeterNiederwieser Grazie - potresti collegarlo per favore? Trovo anche questa situazione esatta gravemente carente nei documenti: Va benissimo definire un nuovo set di sorgenti, ma nessuna informazione su come "agganciarlo a" la compilazione, il jar, il test e quant'altro reali - come fa questo esempio (eccetto per l'aggiunta nel barattolo o creando un nuovo barattolo da quel sourceSet).
stolsvik

Alla riga 6, ottengo "Impossibile risolvere il simbolo" java "" quando utilizzo IntelliJ. Qualche idea sul perché?
Snekse

33

Ecco come ho ottenuto questo risultato senza utilizzare configurations{ }.

apply plugin: 'java'

sourceCompatibility = JavaVersion.VERSION_1_6

sourceSets {
    integrationTest {
        java {
            srcDir 'src/integrationtest/java'
        }
        resources {
            srcDir 'src/integrationtest/resources'
        }
        compileClasspath += sourceSets.main.runtimeClasspath
    }
}

task integrationTest(type: Test) {
    description = "Runs Integration Tests"
    testClassesDir = sourceSets.integrationTest.output.classesDir
    classpath += sourceSets.integrationTest.runtimeClasspath
}

Testato utilizzando: Gradle 1.4 e Gradle 1.6


2
Grazie per la condivisione! È bello vedere implementazioni alternative.
Spina

1
mentre java { srcDir 'src/integrationtest/java' } resources { srcDir 'src/integrationtest/resources' }non è rilevante dal momento che solo redeclares src/<sourceSetName>/...a src/integrationtest/...: qui: cambiare la T maiuscola ad un t inferiore
childno͡.de

Attenzione a questo approccio. compileClasspath += sourceSets.main.runtimeClasspathsta combinando due serie di file. Non esiste una normale risoluzione dei conflitti per le dipendenze. Puoi finire con due versioni della stessa libreria. L'estensione delle configurazioni aiuterà in questo.
chalimartines

20

Questo è stato scritto una volta per Gradle 2.x / 3.x nel 2016 ed è di gran lunga obsoleto !! Dai un'occhiata alle soluzioni documentate in Gradle 4 e versioni successive


Per riassumere entrambe le vecchie risposte (ottieni la migliore e la minima praticabile di entrambi i mondi):

prima alcune parole calde:

  1. per prima cosa, dobbiamo definire sourceSet:

    sourceSets {
        integrationTest
    }
    
  2. successivamente espandiamo il sourceSetfrom test, quindi usiamo il test.runtimeClasspath(che include tutte le dipendenze da testAND teststesso) come classpath per il derivato sourceSet:

    sourceSets {
        integrationTest {
            compileClasspath += sourceSets.test.runtimeClasspath
            runtimeClasspath += sourceSets.test.runtimeClasspath // ***)
        }
    }
    
    • nota ) in qualche modo questa ridichiarazione / estensione per sourceSets.integrationTest.runtimeClasspathè necessaria, ma dovrebbe essere irrilevante poiché runtimeClasspathsi espande sempre output + runtimeSourceSet, non capirlo
  3. definiamo un'attività dedicata solo per l'esecuzione dei test di integrazione:

    task integrationTest(type: Test) {
    }
    
  4. Configurare l' integrationTestuso delle classi di test e dei percorsi di classe. Le impostazioni predefinite del javaplug-in utilizzano l'estensionetest sourceSet

    task integrationTest(type: Test) {
        testClassesDir = sourceSets.integrationTest.output.classesDir
        classpath = sourceSets.integrationTest.runtimeClasspath
    }
    
  5. (opzionale) esecuzione automatica dopo il test

    integrationTest.dependsOn test
    

  6. (opzionale) aggiungi dipendenza da check(quindi viene sempre eseguito quando buildo checkvengono eseguiti)

    tasks.check.dependsOn(tasks.integrationTest)
  7. (opzionale) aggiungi java, risorse a sourceSetper supportare il rilevamento automatico e crea questi "parziali" nel tuo IDE. cioè IntelliJ IDEA creerà automaticamente le sourceSetdirectory java e le risorse per ogni set se non esiste:

    sourceSets {
         integrationTest {
             java
             resources
         }
    }
    

tl; dr

apply plugin: 'java'

// apply the runtimeClasspath from "test" sourceSet to the new one
// to include any needed assets: test, main, test-dependencies and main-dependencies
sourceSets {
    integrationTest {
        // not necessary but nice for IDEa's
        java
        resources

        compileClasspath += sourceSets.test.runtimeClasspath
        // somehow this redeclaration is needed, but should be irrelevant
        // since runtimeClasspath always expands compileClasspath
        runtimeClasspath += sourceSets.test.runtimeClasspath
    }
}

// define custom test task for running integration tests
task integrationTest(type: Test) {
    testClassesDir = sourceSets.integrationTest.output.classesDir
    classpath = sourceSets.integrationTest.runtimeClasspath
}
tasks.integrationTest.dependsOn(tasks.test)

riferito a:

Sfortunatamente, il codice di esempio su github.com/gradle/gradle/subprojects/docs/src/samples/java/customizedLayout/build.gradle o … / gradle /… / withIntegrationTests / build.gradle sembra non gestirlo o ha una differenza / più complesso / per me comunque nessuna soluzione più chiara!


1
(!) A quanto pare, l'uso singolo dei miglioramenti di sourceSet senza configurazioni o output risulta in un errore di idea dopo l'apertura iniziale di un progetto. la dipendenza build (qui: test) per il nuovo "modulo" (qui: integrationTest) non è disponibile al primocompileTestJava
childno͡.de

2
classesDirè stato trasferito al classesDirsgrado 5
deFreitas

grazie per il suggerimento @deFreitas, ho contrassegnato la risposta come obsoleta
childno͡.de


7

Se stai usando

Per fare in modo che IntelliJ riconosca il set di sorgenti personalizzato come root delle sorgenti di test:

plugin {
    idea
}

idea {
    module {
        testSourceDirs = testSourceDirs + sourceSets["intTest"].allJava.srcDirs
        testResourceDirs = testResourceDirs + sourceSets["intTest"].resources.srcDirs
    }
}

2

Ecco cosa funziona per me a partire da Gradle 4.0.

sourceSets {
  integrationTest {
    compileClasspath += sourceSets.test.compileClasspath
    runtimeClasspath += sourceSets.test.runtimeClasspath
  }
}

task integrationTest(type: Test) {
  description = "Runs the integration tests."
  group = 'verification'
  testClassesDirs = sourceSets.integrationTest.output.classesDirs
  classpath = sourceSets.integrationTest.runtimeClasspath
}

A partire dalla versione 4.0, Gradle ora utilizza directory di classi separate per ogni lingua in un set di sorgenti. Quindi, se il tuo script di build utilizza sourceSets.integrationTest.output.classesDir, vedrai il seguente avviso di deprecazione.

Gradle ora utilizza directory di output separate per ogni linguaggio JVM, ma questa build presuppone una singola directory per tutte le classi da un set di origini. Questo comportamento è stato deprecato ed è pianificato per essere rimosso in Gradle 5.0

Per eliminare questo avviso, passa sourceSets.integrationTest.output.classesDirsinvece a. Per ulteriori informazioni, vedere le note sulla versione di Gradle 4.0 .


passare a <hmm> ?? Il tuo prima e dopo sono la stessa cosa.
Merk

-1

Sono nuovo di Gradle, utilizzo Gradle 6.0.1 JUnit 4.12. Ecco cosa ho pensato per risolvere questo problema.

apply plugin: 'java'
repositories { jcenter() }

dependencies {
    testImplementation 'junit:junit:4.12'
}

sourceSets {
  main {
    java {
       srcDirs = ['src']
    }
  }
  test {
    java {
      srcDirs = ['tests']
    }
  }
}

Si noti che la fonte principale e la fonte di test sono referenziate separatamente, una sotto maine una sotto test.

L' testImplementationelemento sotto dependenciesviene utilizzato solo per compilare il sorgente in test. Se il tuo codice principale avesse effettivamente una dipendenza da JUnit, dovresti anche specificare implementationsotto dependencies.

Ho dovuto specificare la repositoriessezione per farlo funzionare, dubito che sia il migliore / unico modo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.