Làm cách nào để thêm bộ nguồn mới vào Gradle?


99

Tôi muốn thêm các bài kiểm tra tích hợp vào bản dựng Gradle của mình (Phiên bản 1.0). Chúng nên chạy riêng biệt với các bài kiểm tra thông thường của tôi vì chúng yêu cầu một ứng dụng web được triển khai tới localhost (chúng kiểm tra ứng dụng web đó). Các bài kiểm tra sẽ có thể sử dụng các lớp được xác định trong bộ nguồn chính của tôi. Làm cách nào để biến điều này thành hiện thực?

Câu trả lời:


114

Điều này khiến tôi mất một lúc để tìm ra và các nguồn trực tuyến không tốt. Vì vậy, tôi muốn ghi lại giải pháp của mình.

Đây là một tập lệnh xây dựng gradle đơn giản có bộ nguồn intTest ngoài bộ nguồn chính và bộ nguồn thử nghiệm:

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
Bạn vẫn cần phải khai báo và định cấu hình tác vụ kiểm tra tích hợp. Về mặt tài liệu, có một java/withIntegrationTestsmẫu trong bản phân phối Gradle đầy đủ.
Peter Niederwieser,

Cảm ơn @PeterNiederwieser Tôi đã sửa tập lệnh xây dựng mẫu của mình.
Spina

2
Tôi đã cố gắng để làm điều này cũng ... cảm ơn bạn rất nhiều vì đăng các giải pháp :)
Igor Popov

@PeterNiederwieser Cảm ơn - bạn có thể liên kết nó lên được không? Tôi cũng thấy tình huống chính xác này thiếu tài liệu nghiêm trọng: Việc xác định một sourceSet mới là rất tốt và tốt, nhưng không có thông tin nào về việc "nối cái này vào" mục tiêu biên dịch, jar, thử nghiệm và whatnot thực tế - như ví dụ này (ngoại trừ việc thêm vào bình, hoặc tạo một bình mới, từ Bộ nguồn đó).
stolsvik

Trên dòng 6, tôi nhận được "Không thể giải quyết biểu tượng 'java'" khi sử dụng IntelliJ. Bất kỳ suy nghĩ về lý do tại sao?
Snekse

33

Đây là cách tôi đạt được điều này mà không cần sử dụng 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
}

Đã kiểm tra bằng cách sử dụng: Gradle 1.4 và Gradle 1.6


2
Cám ơn vì đã chia sẻ! Thật tốt khi thấy các triển khai thay thế.
Spina

1
trong khi java { srcDir 'src/integrationtest/java' } resources { srcDir 'src/integrationtest/resources' }không liên quan vì nó chỉ redeclares src/<sourceSetName>/...đến src/integrationtest/...: ở đây: thay đổi T vốn vào công t thấp
childno͡.de

Hãy cẩn thận với cách tiếp cận này. compileClasspath += sourceSets.main.runtimeClasspathđang kết hợp hai bộ tệp. Không có cách giải quyết xung đột thông thường cho các phụ thuộc. Bạn có thể kết thúc với hai phiên bản của cùng một thư viện. Việc mở rộng cấu hình sẽ giúp làm điều đó.
chalimartines

20

Điều này đã từng được viết cho Gradle 2.x / 3.x vào năm 2016 và đã lỗi thời !! Vui lòng xem các giải pháp được ghi lại trong Gradle 4 trở lên


Để tổng hợp cả hai câu trả lời cũ (lấy tốt nhất và khả thi tối thiểu của cả hai thế giới):

một số lời nói ấm áp đầu tiên:

  1. đầu tiên, chúng ta cần phải xác định sourceSet:

    sourceSets {
        integrationTest
    }
    
  2. tiếp theo, chúng tôi mở rộng sourceSetfrom test, do đó chúng tôi sử dụng test.runtimeClasspath(bao gồm tất cả các tùy thuộc từ testAND testchính nó) làm classpath cho dẫn xuất sourceSet:

    sourceSets {
        integrationTest {
            compileClasspath += sourceSets.test.runtimeClasspath
            runtimeClasspath += sourceSets.test.runtimeClasspath // ***)
        }
    }
    
    • lưu ý ) bằng cách nào đó, khai báo lại / mở rộng cho sourceSets.integrationTest.runtimeClasspathnày là cần thiết, nhưng sẽ không liên quan vì runtimeClasspathluôn mở rộng output + runtimeSourceSet, đừng hiểu
  3. chúng tôi xác định một nhiệm vụ chuyên dụng để chỉ chạy thử nghiệm tích hợp:

    task integrationTest(type: Test) {
    }
    
  4. Định cấu hình các integrationTestlớp thử nghiệm và sử dụng classpath. Các giá trị mặc định từ javaplugin sử dụngtest sourceSet

    task integrationTest(type: Test) {
        testClassesDir = sourceSets.integrationTest.output.classesDir
        classpath = sourceSets.integrationTest.runtimeClasspath
    }
    
  5. (tùy chọn) tự động chạy sau khi kiểm tra

    integrationTest.dependsOn kiểm tra
    

  6. (tùy chọn) thêm phụ thuộc từ check(vì vậy nó luôn chạy khi buildhoặc checkđược thực thi)

    tasks.check.dependsOn(tasks.integrationTest)
  7. (tùy chọn) thêm java, tài nguyên vào sourceSetđể hỗ trợ tự động phát hiện và tạo các "phần tử" này trong IDE của bạn. tức là IntelliJ IDEA sẽ tự động tạo sourceSetthư mục java và tài nguyên cho từng bộ nếu nó không tồn tại:

    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)

đề cập đến:

Thật không may, mã ví dụ trên github.com/gradle/gradle/subprojects/docs/src/samples/java/customizedLayout/build.gradle hoặc … / gradle /… / withIntegrationTests / build.gradle dường như không xử lý được điều này hoặc có một mã khác / phức tạp hơn / đối với tôi không có giải pháp rõ ràng hơn anyway!


1
(!) Hóa ra, việc sử dụng một lần các cải tiến của sourceSet mà không có cấu hình hoặc đầu ra dẫn đến lỗi ý tưởng sau khi mở một dự án ngay lập tức. sự phụ thuộc vào bản dựng (tại đây: thử nghiệm) cho "mô-đun" mới (tại đây: integrationTest) không khả dụng ngay từ đầucompileTestJava
childno͡.de

2
classesDirđã được chuyển đến classesDirstrên lớp 5
deFreitas

cảm ơn vì gợi ý @deFreitas, tôi đã đánh dấu câu trả lời là lỗi thời
childno͡.de 26/02/19


7

Nếu bạn đang sử dụng

Để IntelliJ nhận ra tập nguồn tùy chỉnh là nguồn gốc thử nghiệm:

plugin {
    idea
}

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

2

Đây là những gì phù hợp với tôi kể từ 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
}

Kể từ phiên bản 4.0, Gradle hiện sử dụng các thư mục lớp riêng biệt cho từng ngôn ngữ trong tập nguồn. Vì vậy, nếu tập lệnh xây dựng của bạn sử dụng sourceSets.integrationTest.output.classesDir, bạn sẽ thấy cảnh báo không dùng nữa sau đây.

Gradle hiện sử dụng các thư mục đầu ra riêng biệt cho từng ngôn ngữ JVM, nhưng bản dựng này giả định một thư mục duy nhất cho tất cả các lớp từ một tập nguồn. Hành vi này không được dùng nữa và được lên lịch xóa trong Gradle 5.0

Để loại bỏ cảnh báo này, chỉ cần chuyển sang sourceSets.integrationTest.output.classesDirs. Để biết thêm thông tin, hãy xem ghi chú phát hành Gradle 4.0 .


chuyển sang <hmm> ?? Trước và sau của bạn giống nhau.
Merk

0

Tôi mới sử dụng Gradle, đang sử dụng Gradle 6.0.1 JUnit 4.12. Đây là những gì tôi nghĩ ra để giải quyết vấn đề này.

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

dependencies {
    testImplementation 'junit:junit:4.12'
}

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

Lưu ý rằng nguồn chính và nguồn kiểm tra được tham chiếu riêng biệt, một bên dưới mainvà một bên dưới test.

Các testImplementationdưới mục dependencieschỉ được sử dụng để biên dịch các nguồn trong test. Nếu mã chính của bạn thực sự có phụ thuộc vào JUnit, thì bạn cũng sẽ chỉ định implementationbên dưới dependencies.

Tôi đã phải chỉ định repositoriesphần để làm cho điều này hoạt động, tôi nghi ngờ đó là cách tốt nhất / duy nhất.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.