Gradle: компиляция тестов в проектах со связанными зависимостями

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Для обеспечения обмена кодом тестов между проектами используйте функцию тестовых фикстур в Gradle. Подключите плагин java-test-fixtures и установите зависимости testFixtures между проектами. Таким образом, ваши тесты будут аккуратными и будут следовать принципу DRY.

gradle
Скопировать код
// Подключение плагина в общем проекте (Проект A)
plugins {
    id 'java-test-fixtures'
}

// Добавление зависимости в проект, который использует тестовые фикстуры (Проект B)
dependencies {
    testImplementation(testFixtures(project(':ProjectA')))
}
Кинга Идем в IT: пошаговый план для смены профессии

Использование результатов теста Проекта A в качестве зависимости testCompile для Проекта B

В старых версиях Gradle создайте конфигурацию testArtifacts в файле build.gradle Проекта A для того, чтобы использовать результаты тестирования в качестве зависимости:

gradle
Скопировать код
// В файле build.gradle Проекта A
configurations {
    testArtifacts
}

task testJar(type: Jar) {
    classifier = 'tests'
    from sourceSets.test.output
}

artifacts {
    testArtifacts testJar
}

Укажите данную конфигурацию в зависимостях Проекта B:

gradle
Скопировать код
// В файле build.gradle Проекта B
dependencies {
    testCompile project(path: ':ProjectA', configuration: 'testArtifacts')
}

Не забывайте подключать плагин java в Проекте B для корректного разрешения зависимостей и компиляции.

Обмен тестовыми ресурсами в многомодульных сборках

Если в Проекте A большое количество тестовых классов или ресурсов, создайте для них отдельный источник данных:

gradle
Скопировать код
// Создаем источники данных для тестовых классов в общем проекте
apply plugin: 'java'

sourceSets {
    test {
        java.srcDir 'src/test-shared/java'
        resources.srcDir 'src/test-shared/resources'
    }
}

// Объявляем зависимости в файле build.gradle Проекта B
dependencies {
    testCompile project(':BaseTesting').sourceSets.test.output
}

Лучшие практики при сложных настройках Gradle

Упрощайте конфигурацию, устанавливая прямые зависимости между задачами и создавая пользовательские JAR-файлы по необходимости.

Установка зависимостей для задач

Сделайте так, чтобы Проект B компилировался только после тестирования Проекта A, добавив зависимость от задачи:

gradle
Скопировать код
// В файле build.gradle Проекта B
compileTestJava {
    dependsOn tasks.getByPath(':ProjectA:compileTestJava')
}

Создание пользовательского JAR-файла для тестовых классов

Если для тестовых классов Проекта A нужен особый JAR-файл, то:

gradle
Скопировать код
// В файле build.gradle Проекта A
task testJar(type: Jar) {
    from sourceSets.test.output
    classifier = 'test'
}

artifacts {
    archives testJar
}

Укажите внешний файл JAR как зависимость в Проекте B:

gradle
Скопировать код
// В файле build.gradle Проекта B
dependencies {
    testCompile project(':ProjectA').tasks.testJar.outputs.files
}

Визуализация

Представим процесс на схеме:

Проект A (🚂): предоставляет общие инструменты для тестирования.
Проект B (🛤️): использует инструменты Проекта A для своих тестов.

Конфигурация в Gradle:

🚂 --(тестовая зависимость)--> 🛤️

Связь между проектами похожа на сцепление вагонов:

groovy
Скопировать код
// В файле build.gradle Проекта B
dependencies {
    testImplementation(testFixtures(project(':ProjectA')))
}

Таким образом тесты Проекта B могут использовать инструменты Проекта A и обеспечивается единый процесс тестирования.

Лучшие практики и распространенные ошибки

Обеспечение совместимости версий

Для начала убедитесь в совместимости версий Gradle, и используйте условные операторы для решения возможных проблем:

gradle
Скопировать код
if (GradleVersion.current() < GradleVersion.version("5.6")) {
    // Здесь делаем что-то для обеспечения совместимости со старыми версиями
}

Разделение исходного кода

Основные и тестовые классы не должны перемешиваться. Используйте testFixtures для их разделения:

gradle
Скопировать код
sourceSets {
    main {
        java.srcDirs = ['src/main/java']
        resources.srcDirs = ['src/main/resources']
    }
    testFixtures {
        java.srcDirs = ['src/testFixtures/java']
        resources.srcDirs = ['src/testFixtures/resources']
    }
}

Поддержка многоязычных проектов

Многоязычные проекты требуют переделывание структуры исходных данных:

gradle
Скопировать код
sourceSets {
    test.java.srcDir 'src/test/kotlin'
    test.kotlin.srcDir 'src/test/kotlin'
    // Таким образом, языки могут "жить" вместе
}

Полезные материалы

  1. Структура проектов с помощью Gradle – обзор многопроектных сборок в Gradle.
  2. Управление зависимостями в JVM-проектах – описание методов управления зависимостями для проектов на Java.
  3. Тестирование логики сборки с помощью TestKit – руководство по тестированию плагинов Gradle с TestKit.
  4. Введение в работу с Build Scan® – информация об использовании Gradle Build Scans для анализа сборок.
  5. Видеоурок: введение в многомодульные сборки Gradle – короткий обзор основных понятий многопроектных сборок в Gradle.
Свежие материалы