हाल ही में एक डिप्लॉयमेंट की वजह से तीन माइक्रोसर्विसेज खराब हो गईं, जबकि हर यूनिट टेस्ट, इंटीग्रेशन टेस्ट और मॉक-सर्वर चेक पास हो गया था। टीम ने अपने API mocks को contract testing से बदल दिया। छह महीनों में, कॉन्ट्रैक्ट की संख्या तीन से बढ़कर 47 हो गई और मासिक इंटीग्रेशन-फेलियर (integration-failure) दर दो घटनाओं से घटकर शून्य हो गई।

क्यों mocks आपकी रक्षा नहीं कर सकते

एक मॉक सर्वर केवल उसी रूप (shape) की नकल करता है जिसकी एक कंज्यूमर (consumer) अपेक्षा करता है; यह कभी यह जांच नहीं करता कि प्रोवाइडर (provider) वास्तव में वही रूप प्रदान कर रहा है या नहीं। यदि कोई प्रोवाइडर किसी फ़ील्ड का नाम बदल देता है—मान लीजिए name से display_name कर देता है—तो मॉक अभी भी पुराना पेलोड (payload) ही लौटाता है, कंज्यूमर के टेस्ट पास (green) रहते हैं, और लाइव सिस्टम क्रैश हो जाता है। मंगलवार दोपहर 2 बजे हुई प्रोडक्शन विफलता बिल्कुल ऐसी ही थी: मॉक ने वास्तविक कॉन्ट्रैक्ट के बारे में "झूठ" बोला था।

कॉन्ट्रैक्ट टेस्टिंग कमी को पूरा करती है

कॉन्ट्रैक्ट टेस्टिंग किसी भी कोड के प्रोडक्शन में जाने से पहले API के दोनों पक्षों को एक साझा परिभाषा (shared definition) पर सहमत होने के लिए मजबूर करती है। इसके दो सामान्य दृष्टिकोण मौजूद हैं:

  • Consumer-driven contracts – कंज्यूमिंग सर्विस अपेक्षाएं लिखती है; प्रोवाइडिंग सर्विस उन्हें सत्यापित (validate) करती है। यह उन आंतरिक माइक्रोसर्विसेज के लिए अच्छा काम करता है जो एक साथ विकसित होती हैं।
  • Provider-driven contracts – प्रोवाइडर एक स्पेसिफिकेशन (specification) प्रकाशित करता है; कंज्यूमर्स अपने कोड को उसके विरुद्ध जांचते हैं। सार्वजनिक APIs के लिए यह सामान्य पैटर्न है।

पहला दृष्टिकोण आमतौर पर माइक्रोसर्विस आर्किटेक्चर के भीतर टूटे हुए इंटीग्रेशन को रोकता है।

कंज्यूमर-ड्रिवन कॉन्ट्रैक्ट कैसे काम करता है

  1. कंज्यूमर एक ऐसा टेस्ट लिखता है जो ठीक से बताता है कि उसे प्रोवाइडर से क्या चाहिए।
  2. टेस्ट चलाने से एक pact file जनरेट होती है – एक JSON डॉक्यूमेंट जो उन अपेक्षाओं को रिकॉर्ड करता है।
  3. प्रोवाइडर अपने CI पाइपलाइन में pact file के विरुद्ध अपनी वास्तविक सर्विस चलाता है।
  4. यदि प्रोवाइडर किसी फ़ील्ड को बदलता है, तो वेरिफिकेशन फेल हो जाता है और बिल्ड (build) रुक जाता है।

क्योंकि वेरिफिकेशन वास्तविक प्रोवाइडर कोड पर चलता है, इसलिए किसी भी ब्रेकिंग चेंज (breaking change) को डिप्लॉयमेंट के बाद नहीं, बल्कि शुरुआत में ही पकड़ लिया जाता है।

आपके टेस्ट पिरामिड में कॉन्ट्रैक्ट टेस्ट कहाँ आते हैं

  • Unit tests – तेज़, आइसोलेटेड लॉजिक का परीक्षण करते हैं।
  • Contract tests – मध्यम गति, यह पुष्टि करते हैं कि API समझौते कायम हैं।
  • End-to-end tests – धीमे, पूरे बिजनेस फ्लो का परीक्षण करते हैं।

कॉन्ट्रैक्ट टेस्ट को यूनिट टेस्ट के त्वरित फीडबैक और एंड-टू-एंड सूट्स के व्यापक कवरेज के बीच एक सेतु (bridge) के रूप में मानें। उन इंटीग्रेशन पॉइंट्स को लक्षित करें जो सबसे अधिक बार टूटते हैं और दो या तीन महत्वपूर्ण एंडपॉइंट्स (endpoints) से शुरुआत करें।

वास्तविक दुनिया की अपनाने की कहानी

जिस टीम ने इस लेख की शुरुआत की, उन्होंने अपने सबसे नाजुक कॉल्स (calls) को कवर करने वाले तीन कॉन्ट्रैक्ट्स से शुरुआत की। छह महीने बाद, उनके पास इंटर-सर्विस ट्रैफिक के अधिकांश हिस्से को कवर करने वाले 47 कॉन्ट्रैक्ट्स थे। उस अवधि के दौरान, API टूटने की घटनाएं प्रति माह दो से घटकर शून्य हो गईं।

कब कॉन्ट्रैक्ट टेस्टिंग करना सार्थक नहीं हो सकता है

  • आप एक सोलो डेवलपर हैं जो सभी सेवाओं को एक ही रिपॉजिटरी में रखते हैं।
  • API असाधारण रूप से स्थिर है और वर्षों से नहीं बदली है।
  • आप एक ऐसा प्रोटोटाइप बना रहे हैं जिसे जल्द ही हटा दिया जाएगा।

उन परिदृश्यों में, कॉन्ट्रैक्ट्स को बनाए रखने का ओवरहेड (overhead) इसके लाभ से अधिक हो सकता है।

संभावित नुकसान और उन्हें कैसे कम करें

  • कॉन्ट्रैक्ट्स को उनके द्वारा वर्णित कोड के साथ वर्ज़न (versioned) में रखें।
  • पुराने (stale) कॉन्ट्रैक्ट्स से बचने के लिए हर CI रन में वेरिफिकेशन को ऑटोमेट करें।
  • आकस्मिक खराबी को पकड़ने के लिए पुल रिक्वेस्ट (pull requests) में कॉन्ट्रैक्ट परिवर्तनों की समीक्षा करें।

निष्कर्ष

यदि आप अभी भी खुद को यह समझाने के लिए हाथ से बनाए गए (hand-crafted) मॉक्स पर भरोसा करते हैं कि आपकी सेवाएं बात कर सकती हैं, तो आप एक झूठे वादे पर दांव लगा रहे हैं। कॉन्ट्रैक्ट टेस्टिंग उस दांव को एक सत्यापन योग्य समझौते (verifiable agreement) में बदल देती है, जो प्रोडक्शन तक पहुँचने से पहले ही ब्रेकिंग चेंज को पकड़ लेती है और जैसा कि टीम के आंकड़े दिखाते हैं, यह इंटीग्रेशन विफलताओं को पूरी तरह से समाप्त कर सकती है।