Gradle позволяет разделять приложение на подпроекты. Иногда при определении зависимостей тестовые фикстуры не вписываются ни в структуру production кода, ни в структуру тестового кода. В этой статье мы расскажем о малоизвестной возможности Gradle, которая позволяет тестовым фикстурам занять естественное место в системе зависимостей.

Тестовые фикстуры — это вспомогательные классы и ресурсы, на основе которых строятся тесты. Например:

  • Инициализация класса модели тестовыми данными

  • Вспомогательные методы для обработки и проверки JSON

  • Широко используемые конструкции с мок-объектами

Тестовые фикстуры часто создаются путем выделения кода, который используется в нескольких тестовых классах. Ситуация становится особенно интересной, если такой код необходимо использовать в нескольких Gradle подпроектах.

Проблема: ни тестовый, ни production код

В этом примере у нас есть приложение с тремя Gradle sub-project-ами: app, domain и exporters:

Для тестов в проекте domain требуются конкретные тестовые данные. Они создаются в отдельном классе TestDataFactory. Эта фабрика также могла бы служить полезной основой для тестирования JSON-экспортера в проекте exporters. К сожалению, напрямую определить такую зависимость нельзя. Это ограничение является осознанным архитектурным решением Gradle, поскольку тесты обычно только выполняются и не предоставляют артефакты для других проектов.

Решение: плагин java-test-fixtures

Начиная с Gradle 5.6 тестовые фикстуры поддерживаются на уровне платформы:

Для этого соответствующий плагин Gradle подключается к подпроекту, который предоставляет тестовые фикстуры (пример domain/build.gradle):

plugins {
    id 'java-library'
    id 'java-test-fixtures'
}

dependencies {
    // ...
    testFixturesImplementation 'com.google.guava:guava:31.1-jre'
}

После этого Gradle автоматически создает и настраивает новый SourceSet под названеим testFixtures в дополнение к main и test. Стандартная структура каталогов выглядит следующим образом:

︙
├── domain
│   ├── build.gradle
│   └── src
│       ├── main
│       │   └── java
│       │       └── de/cronn
│       │              └── CustomerEntity.java
│       ├── test
│       │   └── java
│       │       └── de/cronn
│       │              └── ModelTest.java
│       └── testFixtures
│           └── java
│               └── de/cronn
│                      └── TestDataFactory.java
└── exporters
    ├── build.gradle
    ︙

Зависимости тестовых фикстур можно указывать с помощью конфигураций testFixturesImplementation и testFixturesApi. Они работают аналогично конфигурациям implementation и api плагина java-library.

Подключение тестовых фикстур в качестве зависимости

На последнем этапе объявляется зависимость в build.gradle проекта exporters:

dependencies {
    // ...
    testImplementation testFixtures(project(':domain'))
}

При такой конфигурации класс ExportTest из проекта exporters получает доступ к TestDataFactory из проекта domain.

Отдельные проекты

Совместное использование тестовых фикстур возможно не только между подпроектами Gradle, но и между отдельными проектами.

В таких случаях зависимости устанавливаются через опубликованные артефакты. При использовании плагина java-test-fixtures дополнительная настройка не требуется. По умолчанию автоматически создается и публикуется еще один артефакт:

mygroup
├── myproject
│   └── 1.0
│       ├── myproject-1.0-plain.jar
│       ├── myproject-1.0-sources.jar
│       ├── myproject-1.0-test-fixtures.jar
│       ├── myproject-1.0.module
│       └── myproject-1.0.pom

При использовании собственного плагина Gradle maven-publish дополнительная метаинформация сохраняется в файле *.module. 

Благодаря этому во втором проекте зависимости можно объявить в ожидаемом формате:

dependencies {
    // ...
    testImplementation testFixtures("mygroup.myproject:1.0")
}

Поддержка в IDE

Поскольку плагин Gradle основан на уже существующих механизмах SourceSet-ов, поддержка со стороны IDE реализована хорошо. При поиске текста и символов IDE обычно позволяют применять фильтрацию. Результаты поиска можно ограничить тестовым или производственным кодом. При этом тестовые фикстуры классифицируются по-разному:

  • В Eclipse тестовые фикстуры (корректно) относятся к тестовому коду.

  • В IntelliJ тестовые фикстуры считаются производственным кодом. Чтобы изменить их классификацию при фильтрации, можно настроить собственные области видимости.

Ссылки

Документация Gradle по тестовым фикстурам

Присоединяйтесь к русскоязычному сообществу разработчиков на Spring Boot в телеграм — Spring АйО, чтобы быть в курсе последних новостей из мира разработки на Spring Boot и всего, что с ним связано.

Комментарии (0)