빌드 작업 자동화는 모든 소프트웨어 프로젝트에 매우 중요하며, Gradle의 Kotlin DSL을 사용하면 뛰어난 유연성을 제공합니다. 우리의 대화 중에, 우리는 빌드 로직을 중앙화하고 재사용하는 방법을 탐구했으며, 특히 테스트 보고서에 이를 활용하여모든 프로젝트, buildSrc, 그리고 코틀린에서의 맞춤형 작업.

allprojects`와 `subprojects`를 사용하여 Configurations을 중앙 집중화하세요

블록들`allprojects` et `subprojects`당신의`build.gradle.kts`루트는 여러 모듈 프로젝트 전반에 걸쳐 공통 구성을 적용하는 데 기본적입니다.

*allprojects { …​ }: 구성을 적용루트 프로젝트 및 모든 하위 프로젝트. 정의하기에 좋은`group`, 하나의`version`, 또는`repositories`공통의. *subprojects { …​ }`구성을 적용하위 프로젝트에만, 루트 프로젝트를 제외하고. 모듈에 특정한 플러그인을 적용하기에 완벽함 (예`java ou kotlin-jvm) 또는 라이브러리에 공통된 종속성

다음은 예시입니다 :

// build.gradle.kts (projet racine)
plugins {
    base // Appliqué au projet racine
}

allprojects {
    group = "com.example"
    version = "1.0.0"

    repositories {
        mavenCentral()
    }

    tasks.withType<org.gradle.api.tasks.testing.Test> {
        useJUnitPlatform() // Configuration commune des tests pour tous les projets
    }
}

subprojects {
    apply(plugin = "java")
    apply(plugin = "org.jetbrains.kotlin.jvm")

    dependencies {
        implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
    }

}

\==buildSrc: 빌드 로직의 스위스 군용 칼

작업의 로직이 복잡해지거나 재사용해야 할 때,buildSrc선호되는 솔루션입니다. 이는 주요 빌드 스크립트보다 먼저 컴파일되는 특수 Gradle 모듈이며, 이는 모든 빌드의 클래스패스에서 해당 클래스를 사용할 수 있게 합니다.

왜 사용하나요?`buildSrc`작업을 위해?

  • 재사용성정의된 작업 안에`buildSrc`해당 빌드의 모든 프로젝트에 적용할 수 있습니다.

  • 조직빌드 코드를 중앙 집중화하여 더 깔끔하고 유지보수하기 쉽게 만든다.

  • 타입 안전성과 자동 완성: Kotlin 코드 안의`buildSrc`컴파일되어 IDE의 오류 검사와 자동완성을 제공하여 개발 경험을 향상시킵니다.

흐름도`buildSrc`(PlantUML 코드)

이 다이어그램을 생성하려면 아래 코드를 복사하고 PlantUML을 지원하는 도구에 붙여넣으세요.

[source,plantuml]

@startuml skinparam handwritten true skinparam monochrome true

rectangle "Gradle 빌드 프로세스" { component "buildSrc" as BS { file "MyCustomTask.kt" as T file "MyConventionPlugin.kt" as P } 컴포넌트 "Root Project"으로서 RP 컴포넌트 "Subproject A"를 SA로 구성요소 "Subproject B"를 SB로 }

T --\> P : "정의됨 P --\> RP : "적용됨 P --\> SA : "적용됨 P --\> SB : "적용됨

RP --|\> SA : "contains RP --|\> SB : "contains

RP -up-\> BS : "빌드 로직을 위해 의존함 SA -up→ BS : "의존 (빌드 로직을 위한) SB -up-\> BS : "depends on (for build logic)

T 오른쪽에 메모 커스텀 작업 클래스 (예: OpenTestReportTask) 끝 노트

P 오른쪽의 메모 협약 플러그인 작업을 기록하는 미주

@enduml

\== 추상 보고서 작업 생성

테스트 보고서를 관리하기 위해 우리는 모듈식 접근 방식을 설계했습니다 추상 작업 클래스를 사용하여 안에서`buildSrc`. 귀하의 필요에 따라 이 클래스는 상속받을 수 있습니다`DefaultTask` ou de Exec.

\=== 추상적 작업`OpenTestReportTask`(상속받는`DefaultTask`)

파일 시스템이나 다른 Gradle API와 상호작용하는 맞춤 Kotlin 로직이 필요한 경우 이 접근 방식을 사용하는 것이 권장됩니다. 그런 다음 외부 명령을 실행합니다.

[source,kotlin]

패키지 com.yourpackage

import org.gradle.api.DefaultTask 가져오기 org.gradle.api.tasks.Input import org.gradle.api.tasks.TaskAction import java.io.File

추상 클래스 OpenTestReportTask : DefaultTask()

----
----
init {
    group = "verification"
    description = "Opens a test report in Firefox."
    dependsOn("check") // Assure que les rapports sont générés
}

@get:Input
abstract var reportPath: String

@TaskAction
fun openReport() {
    val separator = File.separator
    val reportFile = project.layout.projectDirectory.asFile.toPath()
        .resolve(reportPath.replace("/", separator))
        .toAbsolutePath()
        .toFile()

    if (!reportFile.exists()) {
        logger.warn("Report file does not exist: $reportFile. Ensure 'check' ran.")
        return
    }

    project.exec {
        commandLine("firefox", "--new-tab", reportFile.absolutePath)
    }
    logger.lifecycle("Opened test report: ${reportFile.absolutePath}")
}
----

## }

구체적인 구현

이 클래스들은 추상 작업을 상속받고 보고서의 특정 경로를 정의합니다.

## [source,kotlin]

패키지 com.yourpackage

추상 클래스 ReportUnitTestsTask : OpenTestReportTask() init { Firefox에서 단위 테스트 보고서를 엽니다. reportPath = "build/reports/tests/test/index.html } }

패키지 com.yourpackage

## abstract class ReportFunctionalTestsTask : OpenTestReportTask() { init { description = "파이어폭스에서 기능 테스트 보고서를 엽니다." reportPath = "build/reports/tests/functionalTest/index.html" } }

\=== 작업 기록

안에`build.gradle.kts`당신의 루트 프로젝트:

## [source,kotlin]

tasks.register<com.yourpackage.ReportUnitTestsTask>("reportTests") {} tasks.register<com.yourpackage.ReportFunctionalTestsTask>("reportFunctionalTests") {}

\=== 보고서 작업의 UML 다이어그램 (PlantUML 코드)

아래 코드를 복사하여 PlantUML을 지원하는 도구에 붙여넣으세요.

## [source,plantuml]

@startuml skinparam handwritten true skinparam 단색 true

추상 클래스 DefaultTask { }

추상 클래스 Exec { \+ commandLine(args: String...) \+ exec() }

추상 클래스 OpenTestReportTask 확장 DefaultTask { \+ group: String = "검증 \+ 설명: 문자열 \+ dependsOn("check") \+ abstract reportPath: String \+ openReport() : void }

추상 클래스 AbstractJbakeExecTask는 Exec를 확장합니다 { \+ group: String = "검증 \+ 설명: 문자열 \+ dependsOn("check") \+ 추상 보고상대경로: 문자열 \+ exec() : void }

클래스 ReportUnitTestsTask는 OpenTestReportTask를 확장합니다 { \+ reportPath: String = "build/reports/tests/test/index.html }

클래스 ReportFunctionalTestsTask extends OpenTestReportTask { \+ reportPath: String = "build/reports/tests/functionalTest/index.html }

class ReportJbakeTestsTask extends AbstractJbakeExecTask { \+ reportRelativePath: String = "build/reports/tests/test/index.html }

class ReportJbakeFunctionalTestsTask extends AbstractJbakeExecTask { \+ reportRelativePath: String = "build/reports/tests/functionalTest/index.html }

OpenTestReportTask \<-- ReportUnitTestsTask OpenTestReportTask \<-- ReportFunctionalTestsTask

AbstractJbakeExecTask \<-- ReportJbakeTestsTask AbstractJbakeExecTask \<-- ReportJbakeFunctionalTestsTask

DefaultTask \<|-- OpenTestReportTask Exec \<|-- AbstractJbakeExecTask DefaultTask \<|-- Exec

## @enduml

\== 추상적인 작업`AbstractJbakeExecTask`(상속받는`Exec`)

주로 외부 명령에 변수 인자를 실행하는 작업이라면, 직접 상속받는**실행**더 직접적입니다.

## [source,kotlin]

패키지 com.yourpackage

import org.gradle.api.tasks.Exec import org.gradle.api.tasks.Input import java.io.File

추상 클래스 AbstractJbakeExecTask : Exec() {

----

init { group = "verification" description = "Opens a Jbake project report in Firefox." dependsOn("check") }

@get:Input abstract var reportRelativePath: String

override fun exec() { val separator = File.separator val reportFile = project.layout.projectDirectory.asFile.toPath() .resolve(reportRelativePath.replace("/", separator)) .toAbsolutePath() .toFile()

if (!reportFile.exists()) { logger.warn("Report file does not exist: $reportFile. Ensure 'check' ran.") return }

commandLine("firefox", "--new-tab", reportFile.absolutePath) logger.lifecycle("Attempting to open report: ${reportFile.absolutePath}") super.exec() // Appelle la méthode exec() de la super-classe Exec }

## }

\=== 구체적인 구현을 위한`Exec`

## [source,kotlin]

package com.yourpackage

추상 클래스 ReportJbakeTestsTask : AbstractJbakeExecTask() { init { description = "Firefox에서 Jbake 단위 테스트 보고서를 엽니다. reportRelativePath = "build/reports/tests/test/index.html } }

package com.yourpackage

abstract class ReportJbakeFunctionalTestsTask : AbstractJbakeExecTask() { init { description = "파이어폭스에서 기능 테스트 보고서를 엽니다." reportRelativePath = "build/reports/tests/functionalTest/index.html" } }

\== 작업 가시성`buildSrc`

당신이 정의하는 작업 및 클래스는**buildSrc**이다 :

***보이고 사용 가능한**votre 메인 빌드의 모든 프로젝트(루트 및 하위 프로젝트)에서. 따라서 사용할 수 있습니다`com.yourpackage.ReportUnitTestsTask`안에`allprojects { ... }`. ***실행 불가능한**직접 buildSrc 작업으로서 (예를 들어,`gradle :buildSrc:reportTests`작업이 특정하게 기록되지 않으면 작동하지 않을 것입니다`buildSrc/build.gradle.kts`).`buildSrc`컴파일 모듈일 뿐, 이 메인 빌드 작업에 사용되는 실행 가능한 애플리케이션 모듈이 아닙니다.

테스트를 위한 보고서 실행`buildSrc`자기

Si `buildSrc`자신만의 테스트를 수행하고 보고서를 생성하면, 보고 작업을 직접 기록할 수 있습니다`buildSrc/build.gradle.kts`:

## [source,kotlin]

plugins { `kotlin-jvm` }

저장소 { mavenCentral() }

tasks.withType\<Test\> { useJUnitPlatform() 보고서.html.출력위치.set(레이아웃.빌드디렉터리.dir("보고서/테스트")) }

import com.yourpackage.ReportJbakeTestsTask // 작업 클래스를 가져옵니다

tasks.register\<ReportJbakeTestsTask\>("reportBuildSrcTests") { // Le chemin est déjà défini dans la classe, il pointera vers les rapports de buildSrc }

그 다음에 실행할 수 있습니다 :`./gradlew :buildSrc:test`다음에`./gradlew :buildSrc:reportBuildSrcTests`.

이러한 관행을 채택함으로써 Kotlin DSL을 사용한 Gradle 빌드 시스템을 구축하게 되며, 이는 단순히 강력할 뿐만 아니라 놀랍도록 모듈화 가능하고 유지 보수가 쉬우며 이해하기 쉽습니다.

관련 기사