¿Cómo agrego un nuevo conjunto de fuentes a Gradle?

99

Quiero agregar pruebas de integración a mi compilación de Gradle (Versión 1.0). Deben ejecutarse por separado de mis pruebas normales porque requieren que se implemente una aplicación web en localhost (prueban esa aplicación web). Las pruebas deberían poder usar clases definidas en mi conjunto de fuentes principal. ¿Cómo hago para que esto suceda?

Espina
fuente

Respuestas:

114

Me tomó un tiempo darme cuenta y los recursos en línea no eran excelentes. Así que quería documentar mi solución.

Este es un simple script de compilación de Gradle que tiene un conjunto de fuentes intTest además de los conjuntos de fuentes principal y de prueba:

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
}
Espina
fuente
7
Aún deberá declarar y configurar una tarea de prueba de integración. En términos de documentación, hay una java/withIntegrationTestsmuestra en la distribución completa de Gradle.
Peter Niederwieser
Gracias @PeterNiederwieser He corregido mi script de compilación de muestra.
Spina
2
También estaba tratando de hacer esto ... muchas gracias por publicar la solución :)
Igor Popov
@PeterNiederwieser Gracias, ¿podría vincularlo? También encuentro que esta situación exacta es muy escasa en los documentos: está muy bien definir un nuevo conjunto de fuentes, pero no hay información sobre "enganchar esto" en los objetivos de compilación, jar, prueba y demás, como lo hace este ejemplo (excepto para agregar en el frasco, o haciendo un nuevo frasco, a partir de ese sourceSet).
stolsvik
En la línea 6, aparece "No se puede resolver el símbolo 'java'" cuando uso IntelliJ. ¿Alguna idea sobre por qué?
Snekse
33

Así es como lo logré sin usar 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
}

Probado con: Gradle 1.4 y Gradle 1.6

Mike Rylander
fuente
2
¡Gracias por compartir! Es bueno ver implementaciones alternativas.
Spina
1
mientras que java { srcDir 'src/integrationtest/java' } resources { srcDir 'src/integrationtest/resources' }no es relevante ya que solo redeclares src/<sourceSetName>/...a src/integrationtest/...: aquí: cambiar la T mayúscula a un menor t
childno͡.de
Tenga cuidado con este enfoque. compileClasspath += sourceSets.main.runtimeClasspathestá combinando dos conjuntos de archivos. No existe una resolución de conflictos habitual para las dependencias. Puede terminar con dos versiones de la misma biblioteca. Extender las configuraciones ayudará con eso.
chalimartines
20

¡Esto se escribió una vez para Gradle 2.x / 3.x en 2016 y está muy desactualizado ! Eche un vistazo a las soluciones documentadas en Gradle 4 y versiones posteriores


Para resumir las dos respuestas anteriores (obtenga la mejor y la mínima viabilidad de ambos mundos):

algunas palabras cálidas primero:

  1. primero, necesitamos definir sourceSet:

    sourceSets {
        integrationTest
    }
  2. a continuación, expandimos el sourceSetfrom test, por lo tanto usamos el test.runtimeClasspath(que incluye todas las dependencias de testAND test) como classpath para el derivado sourceSet:

    sourceSets {
        integrationTest {
            compileClasspath += sourceSets.test.runtimeClasspath
            runtimeClasspath += sourceSets.test.runtimeClasspath // ***)
        }
    }
    • nota ) de alguna manera esta redeclaración / extensión sourceSets.integrationTest.runtimeClasspathes necesaria, pero debería ser irrelevante ya que runtimeClasspathsiempre se expande output + runtimeSourceSet, no la entiendas
  3. definimos una tarea dedicada solo para ejecutar pruebas de integración:

    task integrationTest(type: Test) {
    }
  4. Configure las integrationTestclases de prueba y el uso de classpaths. Los valores predeterminados del javacomplemento utilizan eltest sourceSet

    task integrationTest(type: Test) {
        testClassesDir = sourceSets.integrationTest.output.classesDir
        classpath = sourceSets.integrationTest.runtimeClasspath
    }
  5. (opcional) ejecución automática después de la prueba

    integrationTest.dependsOn test
    

  6. (opcional) agregue dependencia de check(para que siempre se ejecute cuando buildo checkse ejecuten)

    tasks.check.dependsOn(tasks.integrationTest)
  7. (opcional) agregue java, recursos para sourceSetadmitir la detección automática y cree estos "parciales" en su IDE. es decir, IntelliJ IDEA creará automáticamente sourceSetdirectorios java y recursos para cada conjunto si no existe:

    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)

refiriéndose a:

Desafortunadamente, el código de ejemplo en github.com/gradle/gradle/subprojects/docs/src/samples/java/customizedLayout/build.gradle o … / gradle /… / withIntegrationTests / build.gradle parece no manejar esto o tiene una / más complejo / para mí no hay una solución más clara de todos modos!

childno͡.de
fuente
1
(!) Como resultado, el uso único de las mejoras de sourceSet sin configuraciones o resultados da como resultado un error de error en la idea después de abrir inicialmente un proyecto. la dependencia de compilación (aquí: prueba) para el nuevo "módulo" (aquí: integrationTest) no está disponible el primerocompileTestJava
childno͡.de
2
classesDirse migró a classesDirsen gradle 5
deFreitas
gracias por la pista @deFreitas, marqué la respuesta como desactualizada
childno͡.de
9

El complemento nebula-facet elimina el texto estándar:

apply plugin: 'nebula.facet'
facets {
    integrationTest {
        parentSourceSet = 'test'
    }
}

Para las pruebas de integración específicamente, incluso esto se hace por usted , solo aplique:

apply plugin: 'nebula.integtest'

Los enlaces del portal de complementos de Gradle para cada uno son:

  1. nebulosa faceta
  2. nebula.integtest
jkschneider
fuente
7

Si estas usando

Para que IntelliJ reconozca el conjunto de fuentes personalizado como raíz de fuentes de prueba:

plugin {
    idea
}

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

Esto es lo que me funciona a partir de 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 partir de la versión 4.0, Gradle ahora usa directorios de clases separados para cada idioma en un conjunto de fuentes. Entonces, si su script de compilación usa sourceSets.integrationTest.output.classesDir, verá la siguiente advertencia de desaprobación.

Gradle ahora usa directorios de salida separados para cada lenguaje JVM, pero esta compilación asume un solo directorio para todas las clases de un conjunto de fuentes. Este comportamiento ha quedado obsoleto y está programado para eliminarse en Gradle 5.0

Para deshacerse de esta advertencia, simplemente cambie a sourceSets.integrationTest.output.classesDirs. Para obtener más información, consulte las notas de la versión de Gradle 4.0 .

Ryan Sobol
fuente
cambiar a <hmm> ?? Tu antes y después son iguales.
Merk
0

Soy nuevo en Gradle y uso Gradle 6.0.1 JUnit 4.12. Esto es lo que se me ocurrió para resolver este problema.

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

dependencies {
    testImplementation 'junit:junit:4.12'
}

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

Observe que se hace referencia a la fuente principal y la fuente de prueba por separado, una debajo mainy otra debajo test.

El testImplementationelemento de abajo dependenciessolo se usa para compilar la fuente en test. Si su código principal en realidad tuviera una dependencia de JUnit, también debería especificar implementationendependencies .

Tuve que especificar el repositories sección para que esto funcione, dudo que sea la mejor / única forma.

hoopyfrood
fuente