Gradle: компиляция тестов в проектах со связанными зависимостями
Быстрый ответ
Для обеспечения обмена кодом тестов между проектами используйте функцию тестовых фикстур в Gradle. Подключите плагин java-test-fixtures
и установите зависимости testFixtures
между проектами. Таким образом, ваши тесты будут аккуратными и будут следовать принципу DRY.
// Подключение плагина в общем проекте (Проект A)
plugins {
id 'java-test-fixtures'
}
// Добавление зависимости в проект, который использует тестовые фикстуры (Проект B)
dependencies {
testImplementation(testFixtures(project(':ProjectA')))
}
Использование результатов теста Проекта A в качестве зависимости testCompile
для Проекта B
В старых версиях Gradle создайте конфигурацию testArtifacts в файле build.gradle
Проекта A для того, чтобы использовать результаты тестирования в качестве зависимости:
// В файле build.gradle Проекта A
configurations {
testArtifacts
}
task testJar(type: Jar) {
classifier = 'tests'
from sourceSets.test.output
}
artifacts {
testArtifacts testJar
}
Укажите данную конфигурацию в зависимостях Проекта B:
// В файле build.gradle Проекта B
dependencies {
testCompile project(path: ':ProjectA', configuration: 'testArtifacts')
}
Не забывайте подключать плагин java
в Проекте B для корректного разрешения зависимостей и компиляции.
Обмен тестовыми ресурсами в многомодульных сборках
Если в Проекте A большое количество тестовых классов или ресурсов, создайте для них отдельный источник данных:
// Создаем источники данных для тестовых классов в общем проекте
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, добавив зависимость от задачи:
// В файле build.gradle Проекта B
compileTestJava {
dependsOn tasks.getByPath(':ProjectA:compileTestJava')
}
Создание пользовательского JAR-файла для тестовых классов
Если для тестовых классов Проекта A нужен особый JAR-файл, то:
// В файле build.gradle Проекта A
task testJar(type: Jar) {
from sourceSets.test.output
classifier = 'test'
}
artifacts {
archives testJar
}
Укажите внешний файл JAR как зависимость в Проекте B:
// В файле build.gradle Проекта B
dependencies {
testCompile project(':ProjectA').tasks.testJar.outputs.files
}
Визуализация
Представим процесс на схеме:
Проект A (🚂): предоставляет общие инструменты для тестирования.
Проект B (🛤️): использует инструменты Проекта A для своих тестов.
Конфигурация в Gradle:
🚂 --(тестовая зависимость)--> 🛤️
Связь между проектами похожа на сцепление вагонов:
// В файле build.gradle Проекта B
dependencies {
testImplementation(testFixtures(project(':ProjectA')))
}
Таким образом тесты Проекта B могут использовать инструменты Проекта A и обеспечивается единый процесс тестирования.
Лучшие практики и распространенные ошибки
Обеспечение совместимости версий
Для начала убедитесь в совместимости версий Gradle, и используйте условные операторы для решения возможных проблем:
if (GradleVersion.current() < GradleVersion.version("5.6")) {
// Здесь делаем что-то для обеспечения совместимости со старыми версиями
}
Разделение исходного кода
Основные и тестовые классы не должны перемешиваться. Используйте testFixtures
для их разделения:
sourceSets {
main {
java.srcDirs = ['src/main/java']
resources.srcDirs = ['src/main/resources']
}
testFixtures {
java.srcDirs = ['src/testFixtures/java']
resources.srcDirs = ['src/testFixtures/resources']
}
}
Поддержка многоязычных проектов
Многоязычные проекты требуют переделывание структуры исходных данных:
sourceSets {
test.java.srcDir 'src/test/kotlin'
test.kotlin.srcDir 'src/test/kotlin'
// Таким образом, языки могут "жить" вместе
}
Полезные материалы
- Структура проектов с помощью Gradle – обзор многопроектных сборок в Gradle.
- Управление зависимостями в JVM-проектах – описание методов управления зависимостями для проектов на Java.
- Тестирование логики сборки с помощью TestKit – руководство по тестированию плагинов Gradle с TestKit.
- Введение в работу с Build Scan® – информация об использовании Gradle Build Scans для анализа сборок.
- Видеоурок: введение в многомодульные сборки Gradle – короткий обзор основных понятий многопроектных сборок в Gradle.