Bagaimana cara menambahkan kumpulan sumber baru ke Gradle?

99

Saya ingin menambahkan pengujian integrasi ke build Gradle saya (Versi 1.0). Mereka harus berjalan secara terpisah dari pengujian normal saya karena mereka memerlukan aplikasi web untuk diterapkan ke localhost (mereka menguji aplikasi web itu). Tes harus dapat menggunakan kelas yang ditentukan dalam kumpulan sumber utama saya. Bagaimana cara mewujudkannya?

Spina
sumber

Jawaban:

114

Ini membutuhkan waktu beberapa saat bagi saya untuk mencari tahu dan sumber daya daring tidak bagus. Jadi saya ingin mendokumentasikan solusi saya.

Ini adalah skrip build gradle sederhana yang memiliki kumpulan sumber intTest selain set utama dan sumber pengujian:

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
}
Spina
sumber
7
Anda masih perlu mendeklarasikan dan mengonfigurasi tugas uji integrasi. Dalam hal dokumentasi, ada java/withIntegrationTestscontoh dalam distribusi Gradle lengkap.
Peter Niederwieser
Terima kasih @PeterNiederwieser, saya telah mengoreksi contoh skrip build saya.
Spina
2
Saya mencoba melakukan ini juga ... terima kasih banyak telah memposting solusinya :)
Igor Popov
@PeterNiederwieser Terima kasih - bisakah Anda menghubungkannya? Saya juga menemukan situasi yang tepat ini sangat kurang dalam dokumen: Semuanya baik dan bagus dalam mendefinisikan sourceSet baru, tetapi tidak ada info tentang "menghubungkan ini ke" kompilasi, jar, pengujian, dan target lain yang sebenarnya - seperti yang dilakukan contoh ini (kecuali untuk menambahkan ke dalam toples, atau membuat toples baru, dari sourceSet itu).
stolsvik
Pada baris 6, saya mendapatkan "Tidak dapat menyelesaikan simbol 'java'" saat menggunakan IntelliJ. Ada pemikiran tentang mengapa?
Snekse
33

Inilah cara saya mencapai ini tanpa menggunakan 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
}

Diuji menggunakan: Gradle 1.4 dan Gradle 1.6

Mike Rylander
sumber
2
Terima kasih telah berbagi! Senang rasanya melihat implementasi alternatif.
Spina
1
sementara java { srcDir 'src/integrationtest/java' } resources { srcDir 'src/integrationtest/resources' }tidak relevan karena hanya menyatakan kembali src/<sourceSetName>/...ke src/integrationtest/...: di sini: mengubah ibukota T ke t yang lebih rendah
childno͡.de
Waspadalah dengan pendekatan ini. compileClasspath += sourceSets.main.runtimeClasspathmenggabungkan dua set file. Tidak ada resolusi konflik biasa untuk dependensi. Anda bisa mendapatkan dua versi dari pustaka yang sama. Memperluas konfigurasi akan membantu dengan itu.
chalimartines
20

Ini pernah ditulis untuk Gradle 2.x / 3.x pada tahun 2016 dan sudah ketinggalan zaman !! Silakan lihat solusi yang didokumentasikan di Gradle 4 dan yang lebih baru


Untuk meringkas kedua jawaban lama (dapatkan yang terbaik dan minimum yang layak dari kedua dunia):

beberapa kata hangat terlebih dahulu:

  1. pertama, kita perlu mendefinisikan sourceSet:

    sourceSets {
        integrationTest
    }
  2. selanjutnya kami memperluas sourceSetdari test, untuk itu kami menggunakan test.runtimeClasspath(yang mencakup semua ketergantungan dari testAND testitu sendiri) sebagai jalur kelas untuk turunan sourceSet:

    sourceSets {
        integrationTest {
            compileClasspath += sourceSets.test.runtimeClasspath
            runtimeClasspath += sourceSets.test.runtimeClasspath // ***)
        }
    }
    • note ) entah bagaimana pernyataan ulang / perpanjangan sourceSets.integrationTest.runtimeClasspathini diperlukan, tetapi harus tidak relevan karena runtimeClasspathselalu berkembang output + runtimeSourceSet, jangan mengerti
  3. kami mendefinisikan tugas khusus hanya untuk menjalankan tes integrasi:

    task integrationTest(type: Test) {
    }
  4. Konfigurasikan integrationTestkelas pengujian dan penggunaan classpath. Default dari javaplugin menggunakantest sourceSet

    task integrationTest(type: Test) {
        testClassesDir = sourceSets.integrationTest.output.classesDir
        classpath = sourceSets.integrationTest.runtimeClasspath
    }
  5. (opsional) otomatis dijalankan setelah pengujian

    integrasiTest.dependsOn test
    

  6. (opsional) tambahkan ketergantungan dari check(sehingga selalu berjalan saat buildatau checkdijalankan)

    tasks.check.dependsOn(tasks.integrationTest)
  7. (opsional) tambahkan java, resource ke sourceSetuntuk mendukung deteksi otomatis dan buat "parsial" ini di IDE Anda. yaitu IntelliJ IDEA akan otomatis membuat sourceSetdirektori java dan resource untuk setiap set jika tidak ada:

    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)

mengacu:

Sayangnya, kode contoh di github.com/gradle/gradle/subprojects/docs/src/samples/java/customizedLayout/build.gradle atau … / gradle /… / withIntegrationTests / build.gradle tampaknya tidak menangani ini atau memiliki perbedaan / lebih kompleks / bagi saya tidak ada solusi yang lebih jelas!

childno͡.de
sumber
1
(!) ternyata, penggunaan tunggal penyempurnaan sourceSet tanpa konfigurasi atau keluaran menghasilkan kesalahan pembuatan dalam gagasan setelah secara inisial membuka proyek. ketergantungan build (di sini: test) untuk "modul" baru (di sini: integrationTest) tidak tersedia setelah pertamacompileTestJava
childno͡.de
2
classesDirdimigrasi ke classesDirspada kelas 5
deFreitas
terima kasih atas petunjuk @deFreitas, saya menandai jawabannya sebagai usang
childno͡.de
9

The nebula-facet Plugin eliminasi boilerplate:

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

Khusus untuk pengujian integrasi, meskipun ini sudah dilakukan untuk Anda , cukup terapkan:

apply plugin: 'nebula.integtest'

Tautan portal plugin Gradle untuk masing-masing adalah:

  1. nebula.facet
  2. nebula.integtest
jkschneider
sumber
7

Jika Anda menggunakan

Untuk membuat IntelliJ mengenali kumpulan sumber khusus sebagai root sumber pengujian:

plugin {
    idea
}

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

Inilah yang berhasil untuk saya sejak 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
}

Mulai versi 4.0, Gradle sekarang menggunakan direktori kelas terpisah untuk setiap bahasa dalam kumpulan sumber. Jadi, jika skrip build Anda menggunakan sourceSets.integrationTest.output.classesDir, Anda akan melihat peringatan penghentian berikut.

Gradle sekarang menggunakan direktori output terpisah untuk setiap bahasa JVM, tetapi build ini mengasumsikan satu direktori untuk semua kelas dari satu set sumber. Perilaku ini sudah tidak digunakan lagi dan dijadwalkan untuk dihapus di Gradle 5.0

Untuk menghilangkan peringatan ini, alihkan saja ke sourceSets.integrationTest.output.classesDirs. Untuk informasi selengkapnya, lihat catatan rilis Gradle 4.0 .

Ryan Sobol
sumber
beralih ke <hmm> ?? Anda sebelum dan sesudahnya sama.
Merk
-1

Saya baru mengenal Gradle, menggunakan Gradle 6.0.1 JUnit 4.12. Inilah yang saya temukan untuk menyelesaikan masalah ini.

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

dependencies {
    testImplementation 'junit:junit:4.12'
}

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

Perhatikan bahwa sumber utama dan sumber pengujian direferensikan secara terpisah, satu di bawah maindan satu di bawah test.

The testImplementationItem di bawah dependencieshanya digunakan untuk mengkompilasi sumber di test. Jika kode utama Anda benar-benar memiliki ketergantungan pada JUnit, Anda juga harus menentukanimplementation bawah dependencies.

Saya harus menentukan repositoriesbagian agar ini berfungsi, saya ragu itu adalah cara terbaik / satu-satunya.

hoopyfrood.dll
sumber