ฉันจะเพิ่มชุดแหล่งที่มาใหม่ใน Gradle ได้อย่างไร


101

ฉันต้องการเพิ่มการทดสอบการรวมเข้ากับ Gradle build ของฉัน (เวอร์ชัน 1.0) พวกเขาควรทำงานแยกจากการทดสอบปกติของฉันเนื่องจากต้องใช้ webapp เพื่อปรับใช้กับ localhost (พวกเขาทดสอบ webapp นั้น) การทดสอบควรสามารถใช้คลาสที่กำหนดไว้ในชุดแหล่งข้อมูลหลักของฉัน ฉันจะทำให้สิ่งนี้เกิดขึ้นได้อย่างไร

คำตอบ:


116

ฉันใช้เวลาพอสมควรในการหาข้อมูลและแหล่งข้อมูลออนไลน์ก็ไม่เพียงพอ ดังนั้นฉันจึงต้องการบันทึกวิธีแก้ปัญหาของฉัน

นี่คือสคริปต์การสร้างการไล่ระดับสีอย่างง่ายที่มีชุดแหล่งที่มา intTest นอกเหนือจากชุดแหล่งที่มาหลักและชุดทดสอบ:

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
คุณยังคงต้องประกาศและกำหนดค่างานทดสอบการรวม ในแง่ของเอกสารมีjava/withIntegrationTestsตัวอย่างในการแจกแจง Gradle แบบเต็ม
Peter Niederwieser

ขอบคุณ @PeterNiederwieser ฉันได้แก้ไขสคริปต์สร้างตัวอย่างของฉันแล้ว
Spina

2
ฉันพยายามทำเช่นนี้เช่นกัน ... ขอบคุณมากสำหรับการโพสต์วิธีแก้ปัญหา :)
Igor Popov

@PeterNiederwieser ขอบคุณ - คุณช่วยเชื่อมโยงได้ไหม ฉันยังพบว่าสถานการณ์ที่แน่นอนนี้ขาดหายไปอย่างมากในเอกสาร: การกำหนด sourceSet ใหม่เป็นสิ่งที่ดีและดี แต่ไม่มีข้อมูลเกี่ยวกับการ "เชื่อมต่อสิ่งนี้เข้ากับ" การคอมไพล์ jar การทดสอบและสิ่งที่ไม่ได้กำหนดเป้าหมายตามตัวอย่างนี้ (ยกเว้นการเพิ่ม ลงในโถหรือสร้างขวดใหม่จากชุดแหล่งข้อมูลนั้น)
stolsvik

ในบรรทัดที่ 6 ฉันได้รับ "ไม่สามารถแก้ไขสัญลักษณ์ 'java'" เมื่อใช้ IntelliJ คิดว่าทำไม?
Snekse

33

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
}

ทดสอบโดยใช้: Gradle 1.4 และ Gradle 1.6


2
ขอบคุณสำหรับการแบ่งปัน! เป็นการดีที่จะเห็นการใช้งานอื่น
Spina

1
ในขณะที่java { srcDir 'src/integrationtest/java' } resources { srcDir 'src/integrationtest/resources' }ไม่เกี่ยวข้องเนื่องจากเพิ่งประกาศsrc/<sourceSetName>/...ไปที่src/integrationtest/...: ที่นี่: เปลี่ยนเมืองหลวง T เป็น t ที่ต่ำกว่า
childno͡.de

ระวังแนวทางนี้ compileClasspath += sourceSets.main.runtimeClasspathกำลังรวมไฟล์สองชุด ไม่มีการแก้ไขข้อขัดแย้งตามปกติสำหรับการอ้างอิง คุณสามารถจบลงด้วยไลบรารีเดียวกันสองเวอร์ชัน การขยายการกำหนดค่าจะช่วยได้
Chalimartines

22

นี่เคยเขียนให้กับ Gradle 2.x / 3.x ในปี 2016 และล้าสมัยไปมาก !! โปรดดูเอกสารโซลูชันใน Gradle 4 ขึ้นไป


เพื่อสรุปคำตอบเก่าทั้งสอง (ให้ได้ดีที่สุดและต่ำสุดของทั้งสองโลก):

คำพูดที่อบอุ่นก่อน:

  1. ก่อนอื่นเราต้องกำหนดsourceSet:

    sourceSets {
        integrationTest
    }
    
  2. ต่อไปเราจะขยายsourceSetจากtestดังนั้นเราจึงใช้test.runtimeClasspath(ซึ่งรวมถึงการพึ่งพาทั้งหมดจากtestAND testเอง) เป็นคลาสพา ธ สำหรับสิ่งที่ได้รับsourceSet:

    sourceSets {
        integrationTest {
            compileClasspath += sourceSets.test.runtimeClasspath
            runtimeClasspath += sourceSets.test.runtimeClasspath // ***)
        }
    }
    
    • หมายเหตุ ) อย่างไรก็ตามsourceSets.integrationTest.runtimeClasspathจำเป็นต้องมีการประกาศซ้ำ / ขยายสำหรับแต่ควรจะไม่เกี่ยวข้องเนื่องจากruntimeClasspathขยายออกเสมอoutput + runtimeSourceSetอย่าได้รับ
  3. เรากำหนดงานเฉพาะสำหรับการเรียกใช้การทดสอบการรวม:

    task integrationTest(type: Test) {
    }
    
  4. กำหนดค่าintegrationTestคลาสทดสอบและคลาสพา ธ ที่ใช้ ค่าเริ่มต้นจากjavaปลั๊กอินใช้test sourceSet

    task integrationTest(type: Test) {
        testClassesDir = sourceSets.integrationTest.output.classesDir
        classpath = sourceSets.integrationTest.runtimeClasspath
    }
    
  5. (ไม่บังคับ)ทำงานอัตโนมัติหลังจากทดสอบ

    integrationTest.dependsOn ทดสอบ
    

  6. (ไม่บังคับ)เพิ่มการอ้างอิงจากcheck(ดังนั้นจึงมักจะทำงานเมื่อbuildหรือcheckถูกดำเนินการ)

    tasks.check.dependsOn(tasks.integrationTest)
    
  7. (ไม่บังคับ)เพิ่ม java ทรัพยากรเพื่อsourceSetรองรับการตรวจจับอัตโนมัติและสร้าง "partials" เหล่านี้ใน IDE ของคุณ เช่น IntelliJ IDEA จะสร้างsourceSetไดเรกทอรี java และทรัพยากรสำหรับแต่ละชุดโดยอัตโนมัติหากไม่มีอยู่:

    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)

อ้างถึง:

โชคไม่ดีที่โค้ดตัวอย่างในgithub.com/gradle/gradle/subprojects/docs/src/samples/java/customizedLayout/build.gradleหรือ… / gradle / … / withIntegrationTests / build.gradleดูเหมือนจะไม่จัดการกับสิ่งนี้หรือมีข้อแตกต่าง / ซับซ้อนมากขึ้น / สำหรับฉันไม่มีทางแก้ไขที่ชัดเจนกว่าอยู่ดี


1
(!) ตามที่ปรากฎการใช้การปรับปรุง sourceSet เพียงครั้งเดียวโดยไม่มีการกำหนดค่าหรือผลลัพธ์ทำให้เกิดข้อผิดพลาดในแนวคิดหลังจากเริ่มต้นเปิดโครงการ การพึ่งพาการสร้าง (ที่นี่: การทดสอบ) สำหรับ "โมดูล" ใหม่ (ที่นี่: integrationTest) ไม่พร้อมใช้งานในตอนแรกcompileTestJava
childno͡.de

2
classesDirถูกย้ายไปclassesDirsที่ gradle 5
deFreitas

ขอบคุณสำหรับคำใบ้ @deFreitas ฉันทำเครื่องหมายคำตอบว่าล้าสมัย
childno͡.de

9

เนบิวลา-แง่ปลั๊กอินกำจัดสำเร็จรูป:

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

สำหรับการทดสอบการรวมโดยเฉพาะแม้ว่าจะทำเพื่อคุณเพียงแค่สมัคร:

apply plugin: 'nebula.integtest'

ลิงก์พอร์ทัลปลั๊กอิน Gradle สำหรับแต่ละลิงก์ ได้แก่ :

  1. nebula.facet
  2. nebula.integtest

7

หากคุณกำลังใช้

หากต้องการให้ IntelliJ รับรู้ชุดแหล่งที่มาที่กำหนดเองเป็นรูทแหล่งทดสอบ:

plugin {
    idea
}

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

2

นี่คือสิ่งที่ใช้ได้ผลสำหรับฉันใน 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
}

ตั้งแต่เวอร์ชัน 4.0 ตอนนี้ Gradle ใช้ไดเร็กทอรีคลาสแยกกันสำหรับแต่ละภาษาในชุดซอร์ส ดังนั้นหากบิลด์สคริปต์ของคุณใช้sourceSets.integrationTest.output.classesDirคุณจะเห็นคำเตือนการเลิกใช้งานต่อไปนี้

ตอนนี้ Gradle ใช้ไดเร็กทอรีเอาต์พุตแยกกันสำหรับแต่ละภาษา JVM แต่บิลด์นี้ถือว่าเป็นไดเร็กทอรีเดียวสำหรับคลาสทั้งหมดจากชุดซอร์ส เลิกใช้พฤติกรรมนี้แล้วและมีกำหนดจะลบออกใน Gradle 5.0

หากต้องการกำจัดคำเตือนนี้ให้เปลี่ยนไปsourceSets.integrationTest.output.classesDirsใช้แทน สำหรับข้อมูลเพิ่มเติมโปรดดูที่บันทึกประจำรุ่น Gradle 4.0


เปลี่ยนเป็น <hmm> ?? ก่อนและหลังของคุณเหมือนกัน
Merk

-1

ฉันเพิ่งเริ่มใช้ Gradle โดยใช้ Gradle 6.0.1 JUnit 4.12 นี่คือสิ่งที่ฉันคิดขึ้นเพื่อแก้ปัญหานี้

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

dependencies {
    testImplementation 'junit:junit:4.12'
}

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

ขอให้สังเกตว่าแหล่งที่มาและการทดสอบแหล่งที่มาหลักมีการอ้างอิงแยกใต้และเป็นหนึ่งภายใต้maintest

testImplementationภายใต้รายการเป็นเพียงใช้สำหรับการรวบรวมแหล่งที่มาในdependencies testถ้ารหัสหลักของคุณจริงมีการพึ่งพา JUnit แล้วคุณยังจะต้องระบุให้อยู่ภายใต้implementationdependencies

ฉันต้องระบุrepositoriesส่วนเพื่อให้สิ่งนี้ใช้งานได้ฉันสงสัยว่าเป็นวิธีที่ดีที่สุด / วิธีเดียว

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.