Многопроектные тестовые зависимости с gradle

У меня есть многопроектная конфигурация, и я хочу использовать 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 не скомпилирует тестовый файл из Project A.

Ответ 1

Устаревшие

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

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

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

Ответ 2

Простым способом является добавление явной зависимости задачи в 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')
}

Ответ 3

Я знаю, что это старый вопрос, но у меня была такая же проблема, и я потратил некоторое время на выяснение того, что происходит. Я использую 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')

Ответ 4

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

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

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

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

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

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

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

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

Ответ 5

Новое решение на основе testJar (поддерживается с поддержкой trnitive dependencies), доступное как плагин gradle:

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

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

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

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

Например, возьмите проект, в котором зависит проект проекта B по проектам A и B имеет не только зависимость от компиляции, но и также тестовой зависимости. Чтобы скомпилировать и запустить тесты B, нам нужны некоторые тестовые вспомогательные классы из A.

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

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

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

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

В B мы ссылаемся на Конфигурация testArchives:

dependencies {
    ...
    testCompile project (path: ':ProjectA', configuration: 'testArchives') 
}

Ответ 6

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

Подобные проблемы, описанные JustACluelessNewbie, возникают в IntelliJ IDEA. Проблема заключается в том, что testCompile project(':core').sourceSets.test.output зависимости 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, в Настройках модуля → Зависимости (область тестирования).

Btw. Это не очень хорошее решение, поэтому стоит подумать о рефакторинге. Сам 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 и используйте опцию "создать отдельный модуль для исходного набора" при импорте.

Ответ 7

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

android {
    sourceSets {
        androidTest {
            java.srcDir project(':A').file("src/androidTest/java")
        }
        test {
            java.srcDir project(':A').file("src/test/java")
        }
    }
}

Ответ 8

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

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

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

Ответ 9

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

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

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

Вуаля!

Ответ 10

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

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

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

Ответ 11

в проекте B:

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

Кажется, работает в 1.7-rc-2