अनुच्छेद २ : TDD दृष्टिकोण के साथ एक Gradle प्लगइन विकसित करें
Publié le 24 September 2025
इस लेख में, हम जानेंगे कि Gradle प्लगिन के लिए एक मजबूत विकास आधार कैसे स्थापित करें, परीक्षण-निर्देशित विकास (TDD - Test-Driven Development) दृष्टिकोण का उपयोग करके। यह विधि सुनिश्चित करती है कि हमारा कोड मजबूत, रखरखाव योग्य और आवश्यकताओं को सटीक रूप से शुरू से ही पूरा करता है।
परियोजना प्रारम्भ
Gradle बहुत सहजता से एक नए प्लगइन के निर्माण को सुविधाजनक बनाता है, कमांड के माध्यम से।gradle init. कोटलिन के साथ एक 'Gradle Plugin' बनाने का चयन करके, हमें एक उपयोग के लिए तैयार प्रोजेक्ट संरचना मिलती है, जिसमें दो महत्वपूर्ण प्रकार के परीक्षण शामिल हैं:
-
इकाई परीक्षण : Situés dans
src/test, वे हमारे प्लगिन के अलग‑अलग घटकों को सत्यापित करने की अनुमति देते हैं, जैसे किसी कार्य की आंतरिक तर्क या किसी एक्सटेंशन की कॉन्फ़िगरेशन। वे तेज़ हैं और इन्हें ग्रैडल की पूर्ण निष्पादन की आवश्यकता नहीं है। -
कार्यात्मक परीक्षण :में स्थित`src/functionalTest`, वे उपयोग करते हैं`GradleRunner`पूरी Gradle बिल्ड चलाने के लिए एक अस्थायी परीक्षण प्रोजेक्ट में। यह हमें नियंत्रित वातावरण में प्लगिन के वास्तविक व्यवहार को सत्यापित करने की अनुमति देता है।
2. हमारा पहला TDD चक्र : एक कार्य रिकॉर्ड करें
हमारी पहली आवश्यकता सरल है: प्लगइन को एक नामित कार्य पंजीकृत करना होगा`printSiteConfig`.
2.1. पहला परीक्षण (जो परीक्षण असफल होता है)
TDD के अनुसार, हम पहले एक परीक्षण लिखते हैं जो इस कार्य की मौजूदगी की जाँच करता है। में`SiteBakerPluginTest.kt`(हमारा यूनिट परीक्षण फ़ाइल), हम जोड़ते हैं:
@Test
fun `plugin registers task`() {
// Créer un projet de test en mémoire
val project = ProjectBuilder.builder().build()
project.plugins.apply("com.cheroliv.site-baker")
// Vérifier que la tâche a bien été enregistrée
assertNotNull(project.tasks.findByName("printSiteConfig"))
}
यह परीक्षण विफल होता है, क्योंकि हमने अभी तक अपने प्लगइन में कोई कोड नहीं लिखा है।
2.2. अगला कोड (परीक्षा पास करना)
अब हम आवश्यक न्यूनतम कोड लिख रहे हैं में`SiteBakerPlugin.kt`ताकि परीक्षा पास हो:
class SiteBakerPlugin: Plugin<Project> {
override fun apply(project: Project) {
// Enregistrer une tâche simple
project.tasks.register("printSiteConfig") { task ->
// ... la logique de la tâche viendra plus tard
}
}
}
हम परीक्षणों को फिर से चला रहे हैं, और वे पास हो रहे हैं. हमारी पहली सुविधा मान्य है.
3. दूसरा चक्र TDD: एक डीएसएल एक्सटेंशन जोड़ें
अगली आवश्यकता उपयोगकर्ताओं को उनके DSL ब्लॉक के माध्यम से हमारे प्लग़िन को कॉन्फ़िगर करने की अनुमति देना है`build.gradle.kts`. हम एक ब्लॉक चाहते हैं`site { … }`जहाँ आप एक कॉन्फ़िगरेशन पथ निर्दिष्ट कर सकते हैं।
3.1. पहला परीक्षण
हम एक परीक्षण जोड़ रहे हैं ताकि यह सत्यापित किया जा सके कि एक्सटेंशन`site`यह ठीक से दर्ज की गई है और हम इसे मान दे सकते हैं।
@Test
fun `plugin registers extension`() {
val project = ProjectBuilder.builder().build()
project.plugins.apply("com.cheroliv.site-baker")
// Récupérer l'extension et lui affecter une valeur
project.extensions
.findByType(SiteExtension::class.java)!!
.configPath
.set("config.yml")
// Vérifier que la valeur a bien été prise en compte
assertEquals(
"config.yml",
project.extensions.findByType(SiteExtension::class.java)?.configPath?.get()
)
}
यह टेस्ट फेल हो जाता है क्योंकि न तो क्लास`SiteExtension`एक्सटेंशन का पंजीकरण भी मौजूद नहीं है।
3.2. कोड फिर
हम क्लास बनाते हैं`SiteBakerExtension.kt`और हम अपडेट करते हैं`SiteBakerPlugin.kt`:
// SiteBakerExtension.kt
open class SiteExtension @Inject constructor(objects: ObjectFactory) {
val configPath: Property<String> = objects.property(String::class.java)
}
// SiteBakerPlugin.kt
class SiteBakerPlugin: Plugin<Project> {
override fun apply(project: Project) {
// Enregistrer l'extension
val extension = project.extensions.create("site", SiteExtension::class.java)
project.tasks.register("printSiteConfig") { task ->
task.doLast {
// On utilisera l'extension plus tard
}
}
}
}
परीक्षण फिर से पास हो रहे हैं।
4. कार्यात्मक परीक्षण: एकीकरण को सत्यापित करें
अब जब इकाइयाँ परीक्षण की गई हैं, हमें यह सुनिश्चित करने की आवश्यकता है कि सब कुछ एक वास्तविक बिल्ड में एक साथ काम करे। यह फ़ंक्शनल परीक्षण की भूमिका है`SiteBakerPluginFunctionalTest.kt`.
4.1. एकीकरण परीक्षण: एक नियंत्रित वातावरण बनाएँ
यह परीक्षण हमारा प्लगइन का उपयोग करके एक वास्तविक प्रोजेक्ट का अनुकरण करेगा। इसे विश्वसनीय होने के लिए, इसेवायुरोधी, यानी इसे मौजूदा फ़ाइलों पर निर्भर नहीं रहना चाहिए। इसे स्वयं सभी आवश्यक शर्तें बनानी चाहिए जो इसके निष्पादन के लिए आवश्यक हैं।
टेस्ट इसलिए:
-
एक बनाना`build.gradle.kts`हमारा प्लगिन और इसका DSL का उपयोग करने वाला परीक्षण.
-
कॉन्फ़िगरेशन फ़ाइल बनाएँ(
(Note: The output preserves the exact characters, including spaces and the parenthesis, as there is no translatable text.)managed-jbake-context.yml) जो प्लगिन को पढ़ना चाहिए। यह परीक्षण की मजबूती के लिए एक महत्वपूर्ण चरण है।
-
कार्य को निष्पादित करें`printSiteConfig`के माध्यम से`GradleRunner`.
-
निर्माण आउटपुट सही है, यह सुनिश्चित करें।
प्रत्येक निष्पादन में इस कॉन्फ़िगरेशन फ़ाइल को कॉपी करके या बनाकर, हम सुनिश्चित करते हैं कि परीक्षण है।पुनरावृत्ति योग्यऔर यह बाहरी स्थिति पर निर्भर नहीं करता है। यह हमारे परीक्षणों को फ़ाइल पढ़ने से संबंधित रिग्रेशन से सुरक्षित रखता है।
@Test fun `can run task with DSL`() {
// 1. Créer un build.gradle.kts de test
buildFile.writeText("""
plugins { id("com.cheroliv.site-baker") }
site { configPath = "managed-jbake-context.yml" }
""".trimIndent())
// 2. Créer le fichier de configuration pour un test contrôlé
val configFile = File(projectDir, "managed-jbake-context.yml")
configFile.writeText("site: { title: 'Mon Site de Test' }") // Contenu YAML simple
// 3. Exécuter la build
val runner = GradleRunner.create()
runner.withPluginClasspath()
runner.withArguments("printSiteConfig")
runner.withProjectDir(projectDir) // Spécifier le répertoire du projet de test
val result = runner.build()
// 4. Vérifier la sortie
assertTrue(result.output.contains("Site config path: managed-jbake-context.yml"))
}
यह परीक्षा तब तक असफल रहेगी जब तक कि कार्य`printSiteConfig`यह एक्सटेंशन का मान वास्तव में उपयोग नहीं करेगा।
4.2. लॉजिक को अंतिम रूप दें
हम टास्क को अद्यतन कर रहे हैं में`SiteBakerPlugin.kt`इसे कॉन्फ़िगर किया गया मान प्रदर्शित करने के लिए :
project.tasks.register("printSiteConfig") { task ->
task.doLast {
println("Site config path: ${extension.configPath.get()}")
}
}
सभी परीक्षण, इकाई और कार्यात्मक, अब पास हैं।
निष्कर्ष
TDD दृष्टिकोण का पालन करते हुए, हमने एक प्लगइन को चरणबद्ध और सुरक्षित तरीके से बनाया। प्रत्येक छोटी सुविधा को तुरंत एक परीक्षण द्वारा मान्य किया जाता है, तेज़ इकाई परीक्षणों से लेकर पूरी एकीकरण को मान्य करने वाले कार्यात्मक परीक्षणों तक।
अपने परीक्षणों को कार्यात्मक बनाने में सावधानी बरतते हुएहर्मेटिक— विशेषकर प्रोग्रामेटिक रूप से आवश्यक कॉन्फ़िगरेशन फ़ाइलों को बनाकर — हम एक अत्यंत मज़बूत सुरक्षा जाल बुन रहे हैं। यह सख़्ती हमें प्रभावी रूप से रिग्रेशन से बचाती है और हमें भविष्य में अधिक जटिल सुविधाएँ जोड़ने का भरोसा देता है, जैसे YAML कॉन्फ़िगरेशन फ़ाइल का पार्सिंग।
यह मजबूत परीक्षण आधार प्लगइन के रखरखाव और भविष्य के विकास के लिए सबसे मूल्यवान संपत्ति है।