Запустите все тесты подпроектов, используя Gradle - PullRequest
0 голосов
/ 22 июня 2019

У меня есть многомодульный проект Android со структурой:

:a
:b
  :c
  :d
    :e

Я пытаюсь запустить отчет jacoco для модуля: b, чтобы он работал на: b,: c,: dи: е без запуска: а.Я хочу, чтобы все отчеты xml находились в общей папке с именами их project.xml (например, bbml, c.xml и т. Д.). У меня довольно стандартная настройка jacoco

task jacocoTestReport(type: JacocoReport, dependsOn: ['testDebugUnitTest', 'createDebugCoverageReport']) {

    reports {
        xml.enabled = true
        xml.destination = file(allTestCoverageDir + project.name + ".xml")
        html.enabled = true
    }

    def fileFilter = [
            '**/R.class',
            '**/R$*.class',
            '**/BuildConfig.*',
            '**/Manifest*.*',
            '**/*Test*.*',
            'android/**/*.*',

            //Dagger 2
            '**/*Dagger*Component*.*',
            '**/*Module.*',
            '**/*Module$*.*',
            '**/*MembersInjector*.*',
            '**/*_Factory*.*',
            '**/*Provide*Factory*.*',
    ]

    def kotlinDebug = [fileTree(dir: "${project.buildDir}/tmp/kotlin-classes/debug", excludes: fileFilter)]
    def mainSrc = files([
            "$project.projectDir/src/main/java",
            "$project.projectDir/src/main/kotlin"
    ])

    sourceDirectories = files([mainSrc])
    classDirectories = files(kotlinDebug)
    executionData = fileTree(dir: project.buildDir, includes: [
            'jacoco/testDebugUnitTest.exec', 'outputs/code-coverage/connected/*coverage.ec'
    ])
}

Но когда я пытаюсьдля циклического прохождения подпроектов в блоке doLast блок doLast никогда не запускается, и попытка получить доступ к подпроектам до этого также показывает, что: a не имеет подпроектов.

Edit Я могу запустить их длякаждый подпроект с ./gradlew b: jacocoTestReport или ./gradlew c: jacocoTestReport и всеми отчетами и в папке с правильными именами.Но по мере роста моего проекта я не хочу запускать десятки команд (по одной для каждого модуля). Мне нужна одна команда ./gradlew b: jacocoTestReport (или что-то подобное), которая выполняется для b и его поддерева

1 Ответ

0 голосов
/ 22 июня 2019

Насколько я понимаю, в данный момент вы используете allprojects {} для настройки всех подпроектов. Хотя это было каноническим для настройки группы проектов в прошлом, сейчас это не рекомендуется. Кроме того, проекты должны использовать публикации для взаимодействия друг с другом, а не копировать файлы через границы проекта. Так что вам нужно сделать две вещи:

  1. Вместо настройки подпроектов из корневого корневого проекта вы должны создать плагин для настройки jacoco и создать конфигурацию, которая будет содержать отчеты.

Для этого создайте предварительно скомпилированный скрипт-плагин в вашем проекте. Идея состоит в том, чтобы создать скрипт сборки kotlin в проекте buildSrc и создать плагин Gradle из этого файла на лету. Поэтому вам следует переместить логику, которая настраивает jacoco, в файл buildSrc/src/main/kotlin/jacoco-conventions.gradle.kts:

plugins {
    jacoco
}

val jacocoTestReport by tasks.getting(JacocoReport::class) {
  // jacoco configuration 
}

configurations.create("jacocoReports") {
    isCanBeResolved = false
    isCanBeConsumed = true
    attributes {
        attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage::class, "jacocoReports"))
    }
    outgoing.artifact(jacocoTestReport.reports.xml.destination) {
        builtBy(jacocoTestReport)
    }
}

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

Плагин скомпилированных скриптов теперь можно применять в проектах, в которых вы хотите собирать показатели jacoco:

// for example in c/build.gradle.kts
plugins {
  `jacoco-conventions`
}

Теперь вы настроили подпроекты для размещения отчетов Jacoco xml в конфигурациях с атрибутом использования jacocoReports.

  1. В корневом проекте создайте задачу, которая копирует отчет из конфигурации.

Для этого нам нужно настроить конфигурацию, которая использует варианты jacocoReports, а затем зависит от вариантов подпроектов:

// main build file
val jacocoReports by configurations.creating {
    isCanBeResolved = true
    isCanBeConsumed = false
    attributes {
        attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage::class, "jacocoReports"))
    }
}

dependencies {
    jacocoReports(project(":b:c"))
    jacocoReports(project(":b:d:e"))
    // other jacocoReports you want to consume
}

tasks.register<Copy>("aggregateJacocoReports") {
    from(jacocoReports)
    into(file("$buildDir/jacoco"))
}

Как видите, конфигурация jacocoReports имеет такой же атрибут использования, что позволяет использовать ее для разрешения файлов, которые находятся в конфигурациях с таким же атрибутом. Затем нам нужно определить, какие отчеты проекта мы хотим использовать. Это конус путем определения зависимостей проекта с использованием конфигурации jacocoReports. Последний шаг - это простая задача копирования, которая копирует файлы в каталог сборки корневого проекта. Так что теперь, когда вы вызываете ./gradlew aggregateJacocoReports, эта задача разрешает все файлы из конфигурации jacocoReports, что, в свою очередь, создает отчет jacoco для всех проектов, от которых зависит корневой проект.

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

У меня есть минимальный пример, который должен помочь вам настроить ваш проект следующим образом: https://github.com/britter/gradle-jacoco-aggregate. Я удалил специальную конфигурацию Android, чтобы она была простой, но я уверен, что вы поймете это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...