Article 3 : Intégration de Jackson pour le Parsing YAML avec TDD dans un Plugin Gradle
Yayınlandı: 25 September 2025
Hedef kitle: karmaşık yapılandırmaları yönetmek isteyen orta seviye Gradle geliştiricileri
Giriş
Gradle eklenti geliştirme yaparken, karmaşık yapılandırma yönetimi yaygın bir görevdir. DSL’yi yüzlerce özellikle yükmelmek yerine, yapılandırmayı YAML gibi harici bir dosyada tanımlamak genellikle daha temiz ve sürdürülebilirdir. Bu makale, güçlü Jackson kütüphanesini kullanarak YAML dosyalarını Kotlin nesnelerine dönüştürmeyi entegre etme konusunda size rehberlik eder ve eklentimizin sağlamlığını garanti altına almak için katı bir TDD yaklaşımı benimser.site-baker.
1. Bağlam : Bizim Eklentimiz `site-baker
Eklentimiz`site-baker`bir statik sitesinin üretimini ve dağıtımını otomatikleştirmek için tasarlanmıştır. Bir YAML yapılandırma dosyasını okuması gerekir.managed-jbake-context.yml) kaynak yolları, dağıtım hedefleri ve Git kimlikleri gibi bilgileri elde etmek için.
Ayrıştırıcı olarak istediğimiz YAML yapılandırması şu şekilde:
bake:
srcPath: "./site/jbake"
destDirPath: "bake"
cname: "cheroliv.com"
pushPage:
from: "bake"
to: "cvs"
repo:
name: "trainings"
repository: "https://github.com/pages-content/pages-content.github.io.git"
credentials:
username: "USERNAME"
password: "SECRET_TOKEN"
branch: "main"
message: "cheroliv.com"
# ... autres configurations (pushMaquette, supabase, etc.)
2. Kotlin’de Yapılandırma Modellemesi
Parsing öncesi, Kotlin’te veri yapımızı tanımlamalıyız. Jackson, bu sınıfları kullanarak YAML içeriğini otomatik olarak eşleyecek.
// plugin/src/main/kotlin/com/cheroliv/site/baker/data/SiteConfiguration.kt
package com.cheroliv.site.baker.data
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory
import com.fasterxml.jackson.module.kotlin.readValue
import com.fasterxml.jackson.module.kotlin.registerKotlinModule
fun parseSiteConfiguration(yaml: String): SiteConfiguration {
val mapper = ObjectMapper(YAMLFactory()).registerKotlinModule()
return mapper.readValue(yaml)
}
data class GitPushConfiguration(
val from: String = "",
val to: String = "",
val repo: RepositoryConfiguration = RepositoryConfiguration(),
val branch: String = "",
val message: String = "",
)
data class RepositoryConfiguration(
val name: String = "",
val repository: String = "",
val credentials: RepositoryCredentials = RepositoryCredentials(),
) {
companion object {
const val ORIGIN = "origin"
const val CNAME = "CNAME"
const val REMOTE = "remote"
}
}
data class RepositoryCredentials(val username: String = "", val password: String = "")
data class SiteConfiguration(
val bake: BakeConfiguration = BakeConfiguration(),
val pushPage: GitPushConfiguration = GitPushConfiguration(),
val pushMaquette: GitPushConfiguration = GitPushConfiguration(),
val pushSource: GitPushConfiguration? = null,
val pushTemplate: GitPushConfiguration? = null,
val supabase: SupabaseContactFormConfig? = null
)
data class BakeConfiguration(
val srcPath: String = "",
val destDirPath: String = "",
val cname: String? = null,
)
// ... (autres data classes pour Supabase, si nécessaire)
Fonksiyon`parseSiteConfiguration`bu, deserileşme için giriş noktamız. Kullanır`ObjectMapper`Jackson’ın, yapılandırılmış ile`YAMLFactory`YAML formatı için ve`registerKotlinModule()`Kotlin’in özelliklerini (özelliklerin varsayılan değerleri gibi) desteklemek için.
3. Jackson’ın `build.gradle.kts’e entegrasyonu
Jackson kullanmak için, gerekli bağımlılıkları eklememiz gerekiyor`build.gradle.kts`bizim modülünün`plugin`(empty)
// plugin/build.gradle.kts
dependencies {
// Jackson for YAML parsing
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.18.3")
implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.18.3")
// ... autres dépendances
}
Kullanıyoruz`jackson-module-kotlin`Kotlin desteği için ve`jackson-dataformat-yaml`YAML formatının yönetimi için.
4. TDD Yaklaşımı: YAML Parsing’ini Test Etme
Şimdi, ayrıştırma mantığımızı doğrulamak için TDD’yi uygulayalım.
4.1. Birim Testi: YAML’i Kotlin Nesnesine Eşleme
Bir birim testi ile başlıyoruz`SiteBakerPluginTest.kt`fonksiyonu kontrol etmek için`parseSiteConfiguration`YAML dizesini bir nesneye doğru bir şekilde dönüştürebilir`SiteConfiguration`.
// plugin/src/test/kotlin/com/cheroliv/site/baker/SiteBakerPluginTest.kt
@Test
fun `can map configuration text to SiteConfiguration object`() {
val yamlString = "../../managed-jbake-context.yml"
.run(::File)
.readText()
.trimIndent()
val config: SiteConfiguration = parseSiteConfiguration(yamlString)
assertEquals("cheroliv.com", config.bake.cname)
assertEquals("main", config.pushPage.branch)
assertEquals("https://github.com/pages-content/pages-content.github.io.git", config.pushPage.repo.repository)
}
Bu test dosyanın içeriğini okur`managed-jbake-context.yml`(testin geçerli olması için mevcut olmalıdır) ve nesne üzerinde iddialar yapar`SiteConfiguration`Sonuçlanan. YAML anahtar değerlerinin doğru şekilde eşlendiğini doğrular.
4.2. Fonksiyonel Test: Yapılandırma Dosyasının Okumasını Doğrula
Eklentinin DSL üzerinden yapılandırma dosyasını okuyabildiğini ve analiz işleminin gerçek bir Gradle ortamında çalıştığından emin olmak için, bir fonksiyonel test ekliyoruz`SiteBakerPluginFunctionalTest.kt`.
Bu test, gerçek bir projede pluginin çalıştırılmasını simüle ettiği için çok önemlidir. Olmalıhermetik, yani kendisi dosyayı oluşturmalıdır`managed-jbake-context.yml`kontrollü bir içerikle, testin tekrarlanabilirliğini ve izolasyonunu sağlamak için.
// plugin/src/functionalTest/kotlin/com/cheroliv/site/baker/SiteBakerPluginFunctionalTest.kt
@Test
fun `config file contains good data`(){
val configContent = configFile.readText(UTF_8)
// Vérifications comme dans vos commentaires
assertTrue(configContent.contains("bake"))
assertTrue(configContent.contains("pushPage"))
assertTrue(configContent.contains("repository"))
}
Bu fonksiyonel test, testin geçici dizinine kopyalanan yapılandırma dosyasının beklenen verileri içerdiğini doğrular. YAML’i doğrudan Kotlin nesnesine ayrıştırmazsa da, dosyanın varlığını ve içeriğini doğrular; bu, eklenti tarafından ayrıştırma öncesinde gereken temel bir adımdır.
5. Parsing Akışı Görselleştirme
Aşağıdaki diyagram, YAML yapılandırması ayrıştırılırken veri akışı ve etkileşimlerini gösterir :
@startuml
actor "Utilisateur Gradle" as User
participant "build.gradle.kts" as BuildScript
participant "SiteBakerPlugin" as Plugin
participant "SiteExtension" as Extension
participant "managed-jbake-context.yml" as ConfigFile
participant "parseSiteConfiguration()" as Parser
participant "SiteConfiguration (Objet Kotlin)" as KotlinObject
User -> BuildScript : Applique le plugin et configure le DSL
BuildScript -> Plugin : apply()
Plugin -> Extension : Crée et enregistre l'extension 'site'
User -> BuildScript : site { configPath = "..." }
BuildScript -> Extension : Définit configPath
Plugin -> ConfigFile : Lit le fichier (via configPath)
ConfigFile --> Plugin : Contenu YAML
Plugin -> Parser : Appelle parseSiteConfiguration(yamlString)
Parser -> KotlinObject : Mappe le YAML en objet SiteConfiguration
KotlinObject --> Plugin : Retourne l'objet configuré
@enduml
Sonuç
TDD yaklaşımını izleyerek, Jackson kütüphanesini YAML yapılandırma dosyalarını Kotlin nesnelerine ayrıştırmak için başarıyla Gradle eklentimizle entegre ettik. Bu yöntem, bize şunları sağladı:
-
Açıkça modellemekKotlin veri sınıflarıyla yapılandırma.
-
Parsing mantığını doğrulahedefli birim testleri ile
-
Entegrasyonu sağlamakgerçek Gradle ortamında, kapalı fonksiyonel testler sayesinde.
Bu sağlam temel, bu yapıya dayalı özelliklerle eklentimizi genişletirken bize büyük güven sağlarken, kodun sürdürülebilirliğini ve sağlamlığını da garanti altına alır. YAML ayrıştırma artık eklentimizin güvenilir ve test edilmiş bir özelliğidir.site-baker.