Многопроектные тестовые зависимости с Gradle - PullRequest
124 голосов
/ 13 апреля 2011

У меня есть многопроектная конфигурация, и я хочу использовать gradle.

Мои проекты такие:

  • Проект A

    • -> src/main/java
    • -> src/test/java
  • Проект B

    • -> src/main/java (зависит от src/main/java от проекта A )
    • -> src/test/java (зависит от src/test/java от проекта A )

Мой Проект B build.gradle Файл выглядит следующим образом:

apply plugin: 'java'
dependencies {
  compile project(':ProjectA')
}

Задача compileJava отлично работает, но compileTestJava не компилирует тестфайл из проекта A .

Ответы [ 12 ]

108 голосов
/ 01 ноября 2011

устарел

В Проект B , вам просто нужно добавить зависимость testCompile:

dependencies {
  ...
  testCompile project(':A').sourceSets.test.output
}

Протестировано с Gradle 1.7.

54 голосов
/ 13 апреля 2011

Простой способ - добавить явную зависимость задачи в ProjectB:

compileTestJava.dependsOn tasks.getByPath(':ProjectA:testClasses')

Сложный (но более понятный) способ - создать дополнительную конфигурацию артефактов для ProjectA:

task myTestsJar(type: Jar) { 
  // pack whatever you need...
}

configurations {
  testArtifacts
}

artifacts {
   testArtifacts myTestsJar
}

и добавьте зависимость testCompile для ProjectB

apply plugin: 'java'
dependencies {
  compile project(':ProjectA')
  testCompile project(path: ':ProjectA', configuration: 'testArtifacts')
}
17 голосов
/ 05 февраля 2014

Я знаю, что это старый вопрос, но у меня была такая же проблема, и я потратил некоторое время на выяснение того, что происходит.Я использую Gradle 1.9.Все изменения должны быть в ProjectB build.gradle

Чтобы использовать тестовые классы из ProjectA в тестах ProjectB:

testCompile files(project(':ProjectA').sourceSets.test.output.classesDir)

Чтобы убедиться, что свойство sourceSets доступно для ProjectA:

evaluationDependsOn(':ProjectA')

Чтобы убедиться, что тестовые классы из ProjectA действительно присутствуют при компиляции ProjectB:

compileTestJava.dependsOn tasks.getByPath(':ProjectA:testClasses')
13 голосов
/ 31 января 2014

Я сам недавно столкнулся с этой проблемой, и мужик, это сложные вопросы, чтобы найти ответы.

Ошибка, которую вы делаете, заключается в том, что проект должен экспортировать свои тестовые элементы так же, как он экспортирует свои основные артефакты и зависимости.

То, с чем я лично добился гораздо большего успеха, - это создание нового проекта в Gradle. В вашем примере я бы назвал это

Проект A_Test -> src / main / java

Я бы поместил в src / main / java файлы, которые у вас сейчас есть в Project A / src / test / java. Сделайте любые зависимости testCompile вашего Project A зависимости от проекта Project A_Test.

Затем сделайте Project A_Test зависимостью testCompile проекта B.

Это не логично, когда вы подходите к этому с точки зрения автора обоих проектов, но я думаю, что это имеет большой смысл, когда вы думаете о таких проектах, как junit и scalatest (и другие. Даже если эти платформы тестируют связанные с ними, они не считаются частью «тестовых» целей в их собственных инфраструктурах - они создают первичные артефакты, которые другие проекты просто используют в своей тестовой конфигурации. Вы просто хотите следовать той же схеме.

Попытка сделать другие ответы, перечисленные здесь, не сработала лично для меня (с использованием Gradle 1.9), но я обнаружил, что шаблон, который я здесь описываю, в любом случае является более чистым решением.

11 голосов
/ 30 декабря 2015

Новое решение на основе testJar (поддерживается trnsitive зависимость), доступное в качестве подключаемого модуля:

https://github.com/hauner/gradle-plugins/tree/master/jartest

https://plugins.gradle.org/plugin/com.github.hauner.jarTest/1.0

Из документации

Если у вас многопроектная сборка Gradle, у вас может быть тест зависимости между подпроектами (что, вероятно, является подсказкой, что ваш проекты не очень хорошо структурированы).

Например, предположим, что проект зависит от подпроекта B в проектах A и B не только зависимость компиляции от A, но также тестовая зависимость. Для компиляции и запуска тестов B нам нужны некоторые тестовые вспомогательные классы от A.

По умолчанию Gradle не создает JAR-артефакт из тестовой сборки. вывод проекта.

Этот плагин добавляет конфигурацию testArchives (на основе testCompile) и задача jarTest для создания jar из набора тестовых источников (с к названию банки добавлен тест классификатора). Тогда мы можем зависеть в B от конфигурация testArchives для A (которая также будет включать переходные зависимости А).

В A мы добавим плагин для build.gradle:

apply plugin: 'com.github.hauner.jarTest'

В Б мы ссылаемся на Конфигурация testArchives выглядит так:

dependencies {
    ...
    testCompile project (path: ':ProjectA', configuration: 'testArchives') 
}
9 голосов
/ 24 мая 2016

Пожалуйста, прочтите обновление ниже.

Подобные проблемы, описанные JustACluelessNewbie, возникают в IntelliJ IDEA.Проблема в том, что зависимость testCompile project(':core').sourceSets.test.output фактически означает: «зависеть от классов, сгенерированных задачей сборки gradle».Поэтому, если вы откроете чистый проект, в котором классы еще не созданы, IDEA не распознает их и сообщит об ошибке.

Чтобы решить эту проблему, вы должны добавить зависимость от тестовых исходных файлов рядом с зависимостью от скомпилированных классов.

// First dependency is for IDEA
testCompileOnly files { project(':core').sourceSets.test.java.srcDirs }
// Second is for Gradle
testCompile project(':core').sourceSets.test.output

Вы можете наблюдать зависимости, распознаваемые IDEA в Настройки модуля -> Зависимости (область тестирования) .

Кстати.Это не очень хорошее решение, поэтому стоит подумать о рефакторинге.Сам Gradle имеет специальный подпроект, содержащий только классы поддержки тестирования.См. https://docs.gradle.org/current/userguide/test_kit.html

Обновление 2016-06-05 Чем больше я думаю о предлагаемом решении, тем меньше оно мне нравится.Есть несколько проблем с ним:

  1. Это создает две зависимости в IDEA.Один указывает на тестирование источников, другой на скомпилированные классы.И очень важно, в каком порядке эти зависимости признаются IDEA.Вы можете поиграть с ним, изменив порядок зависимостей в Настройках модуля -> вкладка Зависимости.
  2. Объявляя эти зависимости, вы излишне загрязняете структуру зависимостей.

Так что же является лучшим решением?На мой взгляд, это создание нового пользовательского набора исходных кодов и добавление в него общих классов.На самом деле авторы проекта Gradle сделали это, создав исходный набор testFixtures.

Чтобы сделать это, вам просто необходимо:

  1. Создать исходный набор и добавить необходимые конфигурации.Проверьте этот плагин сценария, используемый в проекте Gradle: https://github.com/gradle/gradle/blob/v4.0.0/gradle/testFixtures.gradle
  2. Объявите правильную зависимость в зависимом проекте:

    dependencies {
        testCompile project(path: ':module-with-shared-classes', configuration: 'testFixturesUsageCompile')
    }
    
  3. Импортируйте проект Gradle в IDEA и используйте "createопция "отдельный модуль для каждого набора источников" при импорте.
7 голосов
/ 05 октября 2016

Решение Феслера у меня не сработало, когда я попробовал его построить проект Android (Gradle 2.2.0).Поэтому мне пришлось ссылаться на обязательные классы вручную:

android {
    sourceSets {
        androidTest {
            java.srcDir project(':A').file("src/androidTest/java")
        }
        test {
            java.srcDir project(':A').file("src/test/java")
        }
    }
}
3 голосов
/ 22 июня 2018

Я так опоздал на вечеринку (теперь это Gradle v4.4), но для всех, кто найдет это:

Предполагая, что:

~/allProjects
|
|-/ProjectA/module-a/src/test/java
|
|-/ProjectB/module-b/src/test/java

Перейдите к build.gradle проекта B (который нуждается в нескольких тестовых классах из A) и добавьте следующее:

sourceSets {
    String sharedTestDir = "${projectDir}"+'/module-b/src/test/java'
    test {
        java.srcDir sharedTestDir
    }
}

или (при условии, что ваш проект называется "ProjectB")

sourceSets {
    String sharedTestDir = project(':ProjectB').file("module-b/src/test/java")
    test {
        java.srcDir sharedTestDir
    }
}

Voila!

2 голосов
/ 14 мая 2018

Если у вас есть фиктивные зависимости, которые нужно разделить между тестами, вы можете создать новый проект projectA-mock и затем добавить его в качестве тестовой зависимости к ProjectA и ProjectB:

dependencies {
  testCompile project(':projectA-mock')
}

Это простое решение для совместного использования фиктивных зависимостей, но если вам нужно запустить тесты из ProjectA в ProjectB, используйте другое решение.

2 голосов
/ 24 мая 2016

Некоторые другие ответы так или иначе вызывали ошибки - Gradle не обнаружил тестовые классы из других проектов, или проект Eclipse имел недопустимые зависимости при импорте.Если у кого-то есть такая же проблема, я предлагаю перейти к:

testCompile project(':core')
testCompile files(project(':core').sourceSets.test.output.classesDir)

Первая строка заставляет Eclipse связывать другой проект как зависимость, поэтому все источники включены и обновлены.Второй позволяет Gradle фактически видеть источники, не вызывая при этом каких-либо недопустимых ошибок зависимостей, как testCompile project(':core').sourceSets.test.output.

...