Як додати новий набір джерел до Gradle?


99

Я хочу додати тести інтеграції до моєї збірки Gradle (версія 1.0). Вони повинні працювати окремо від моїх звичайних тестів, тому що вони вимагають розгортання веб-додатка на localhost (вони тестують цей веб-додаток). Тести повинні мати можливість використовувати класи, визначені в моєму основному наборі джерел. Як це зробити?

Відповіді:


114

Це зайняло деякий час, щоб зрозуміти, і інтернет-ресурси не були чудовими. Тому я хотів задокументувати своє рішення.

Це простий сценарій побудови gradle, який має набір джерела 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.
Петер Нідервізер

Дякую @PeterNiederwieser Я виправив свій зразок сценарію збірки.
Спіна

2
Я теж намагався це зробити ... велике спасибі за розміщення рішення :)
Ігор Попов

@PeterNiederwieser Дякую - не могли б ви зв’язати? Я також вважаю, що саме такої ситуації дуже бракує в документах: все добре і добре визначає новий sourceSet, але ніякої інформації про "підключення цього" до фактичних цілей компіляції, jar, тесту та чого завгодно - як це робить цей приклад (за винятком додавання в банку або виготовлення нової банки з цього джерела).
stolsvik

У рядку 6 я отримую "Не вдається розпізнати символ 'java'" під час використання IntelliJ. Будь-які думки про те, чому?
Снексе

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
Дякую, що поділились! Добре бачити альтернативні реалізації.
Спіна

1
в той час java { srcDir 'src/integrationtest/java' } resources { srcDir 'src/integrationtest/resources' }як не є актуальним, оскільки він просто оголошує src/<sourceSetName>/...на src/integrationtest/...: тут: змініть
велику величину

Остерігайтеся такого підходу. compileClasspath += sourceSets.main.runtimeClasspathпоєднує два набори файлів. Не існує звичайного вирішення конфліктів для залежностей. Ви можете отримати дві версії однієї бібліотеки. Розширення конфігурацій допоможе в цьому.
chalimartines

20

Це колись було написано для Gradle 2.x / 3.x у 2016 році і воно вже застаріло !! Будь ласка, ознайомтесь із задокументованими рішеннями у Gradle 4 та новіших версіях


Підсумовуючи обидві старі відповіді (отримайте найкращу та мінімальну життєздатність обох світів):

спочатку кілька теплих слів:

  1. по-перше, нам потрібно визначити sourceSet:

    sourceSets {
        integrationTest
    }
  2. далі ми розширюємо sourceSetfrom 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підтримки автоматичного виявлення та створіть ці «часткові елементи» у вашій IDE. тобто IntelliJ IDEA автоматично створюватиме sourceSetкаталоги java та ресурси для кожного набору, якщо він не існує:

    sourceSets {
         integrationTest {
             java
             resources
         }
    }

тл; д-р

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було перенесено до classesDirs5
ступеня

дякую за підказку @deFreitas, я позначив відповідь як застарілу
childno͡.de

9

Туманність фасетки плагіна усуває шаблонний:

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

Для тестів інтеграції, навіть це робиться для вас , просто застосуйте:

apply plugin: 'nebula.integtest'

Посилання на портал плагіна Gradle для кожного з них:

  1. туманність.фасет
  2. туманність.інттег

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> ?? Ваші до і після однакові.
Мерк,

0

Я новачок у 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']
    }
  }
}

Зверніть увагу, що на основне джерело та тестове джерело посилаються окремо, одне під mainта одне під test.

testImplementationПункт під dependenciesвикористовується тільки для компіляції вихідного в test. Якщо ваш основний код насправді мав залежність від JUnit, тоді ви також вказали б implementationпідdependencies .

Мені довелося вказати repositoriesрозділ, щоб це працювало, я сумніваюся, що це найкращий / єдиний спосіб.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.