मैंने हाल ही में एक परीक्षण सूट पर काम किया है जो अविश्वसनीय होने के कारण उपयोग करने के लिए वास्तव में निराशाजनक था।
परीक्षण सूट जिस एप्लिकेशन को लक्षित कर रहा था वह एक रेल एपीआई-केवल एप्लिकेशन था। परीक्षण जावास्क्रिप्ट में चक्रम नामक ढांचे का उपयोग करके लिखे गए थे, "JSON REST एंडपॉइंट्स पर एंड टू एंड टेस्ट करने के लिए डिज़ाइन किया गया एक एपीआई परीक्षण ढांचा"।
परीक्षण सूट के साथ समस्या यह थी कि यह नियतात्मक नहीं था। एक फ़ंक्शन या प्रोग्राम नियतात्मक होता है यदि, समान इनपुट दिए जाने पर, यह हमेशा समान आउटपुट देता है।
यह विशेष परीक्षण सूट पहले रन पर पास होगा, दूसरे रन पर पास होगा, फिर तीसरे रन पर विफल हो जाएगा, बिना एप्लिकेशन कोड या टेस्ट कोड में बदलाव किए बिना।
मैंने पाया कि मैं एक rake db:reset
करके टेस्ट सूट को वापस पासिंग में ला सकता हूं . परीक्षण, जो रेल अनुप्रयोग के विकास परिवेश पर संचालित होता है, न कि परीक्षण परिवेश पर, यह इस बात पर निर्भर करता है कि परीक्षण सूट के चलने के समय रेल अनुप्रयोग का डेटाबेस एक निश्चित स्थिति में है।
कभी-कभी मैं एक ताजा वरीयता प्राप्त डेटाबेस से शुरू कर सकता था, परीक्षण सूट चला सकता था, और फिर दूसरी बार सफलतापूर्वक परीक्षण सूट चला सकता था। मैं परीक्षण सूट को तीन या अधिक बार चलाने में सक्षम हो सकता हूं। लेकिन अक्सर, परीक्षण सूट किसी भी तरह डेटा को गड़बड़ कर देता है और मुझे एक और rake db:reset
करना होगा। डेटा को उस स्थिति में वापस लाने के लिए जिसका परीक्षण सूट सफलतापूर्वक उपयोग कर सकता है।
यह बिल्कुल नहीं है कि चीजें कैसी होनी चाहिए। एक परीक्षण सूट केवल एक कारण से विफल होना चाहिए:जिस कोड का वह परीक्षण कर रहा है वह ठीक से काम करना बंद कर देता है।
इसके बजाय क्या किया जाना चाहिए था
तो अगर यह परीक्षण सूट एक समस्याग्रस्त तरीके से स्थापित किया गया था, तो क्या इसे करने का सही तरीका होता?
समस्या की जड़ यह थी कि परीक्षण सूट मानव द्वारा मैन्युअल रूप से किए जा रहे डेटाबेस रीसेट पर निर्भर था। इसके बजाय, परीक्षण सूट में प्रत्येक व्यक्तिगत परीक्षण को चलने से पहले डेटाबेस को स्वचालित रूप से एक स्वच्छ और तैयार स्थिति में रखना चाहिए। (चलने के बाद डेटाबेस को वाइप करना एक परीक्षण के लिए भी विशिष्ट है, इसलिए यह अपने डेटा को अन्य परीक्षणों में "लीक" नहीं करता है। यह सख्ती से आवश्यक नहीं है यदि प्रत्येक परीक्षण चलने से पहले डेटाबेस को साफ़ करता है, लेकिन यह एक अच्छा सुरक्षात्मक उपाय है। )
परीक्षण सूट को रेल एप्लिकेशन के परीक्षण वातावरण को भी लक्षित करना चाहिए था न कि विकास के माहौल को। विकास के माहौल में एक डेवलपर की कार्रवाइयां परीक्षण सूट के काम और इसके विपरीत नहीं होनी चाहिए।
अन्य प्रकार की समस्यात्मक निर्भरताएं
मेरी कहानी में, समस्याग्रस्त निर्भरता एक डेटाबेस था जो ठीक से साफ नहीं हो रहा था।
एक अन्य प्रकार की समस्याग्रस्त निर्भरता एक नेटवर्क अनुरोध है। कल्पना कीजिए कि आपके पास एक परीक्षण सूट है जो Twilio API को हिट करता है। आप मंगलवार को टेस्ट सूट चलाते हैं और यह पास हो जाता है। फिर बुधवार को आप वही परीक्षण सूट चलाते हैं और यह विफल हो जाता है। आप से अनजान, Twilio में खराबी आ रही है, और इसीलिए आपका परीक्षण सूट विफल हो गया है। कुछ मिनट बाद समस्या का समाधान हो जाता है और आपका परीक्षण सूट फिर से पास हो जाता है।
यह इस विचार पर वापस जाता है कि एक परीक्षण केवल एक कारण से विफल होना चाहिए, और वह यह है कि यदि आपका एप्लिकेशन कोड काम करना बंद कर देता है।
यदि आपको नेटवर्क के साथ इंटरैक्ट करने वाले कोड के लिए परीक्षण लिखने की आवश्यकता है, तो इसे करने का एक बेहतर तरीका (यदि आप रूबी/रेल का उपयोग कर रहे हैं) वीसीआर जैसे टूल का उपयोग करना है जो आपको नेटवर्क अनुरोधों को रिकॉर्ड करने देता है और फिर उन्हें वास्तव में बिना फिर से चलाता है इंटरनेट का उपयोग करना।
मामले जब बाहरी निर्भरता ठीक होती है
यह तर्क दिया जा सकता है कि यदि कोई एप्लिकेशन ट्विलियो एपीआई पर निर्भर करता है और ट्विलियो एपीआई नीचे चला गया है, तो एप्लिकेशन वास्तव में टूट गया है और इसलिए परीक्षण वास्तव में विफल होना चाहिए। हम इस विचार को इस विचार के साथ कैसे मिला सकते हैं कि परीक्षण बाहरी परिस्थितियों पर निर्भर नहीं होने चाहिए?
इन दोनों चीजों के बीच सामंजस्य स्थापित करने का तरीका एकीकरण परीक्षण . के बीच अंतर करना है , जो एक साथ कई परतों या प्रणालियों का परीक्षण करते हैं, और इकाई परीक्षण , जो अलग-अलग कार्यक्षमता के एक टुकड़े का परीक्षण करता है।
यदि एक टीम को एक सचेत निर्णय लेना था कि उनके परीक्षणों का एक निश्चित सेट नेटवर्क पर बाहरी सेवाओं को प्रभावित करने वाला था, तो कई प्रणालियों का एक साथ परीक्षण किया जा सकता है, तो इसमें कुछ भी "गलत" नहीं है। (विकल्प यह होगा कि उन प्रणालियों को एक साथ परीक्षण करने का प्रयास न करने का निर्णय लिया जाए।) इस परिदृश्य में टीम को केवल यह पता होना चाहिए कि उनके नेटवर्क-निर्भर एकीकरण परीक्षण सूट की नियतात्मक होने की गारंटी नहीं है और शायद कभी-कभी बाहर निकल जाएगा . इस तरह के एक परीक्षण सूट को उन परीक्षणों के सेट से अलग रहना चाहिए जो डेवलपर्स अपनी मशीनों पर प्रतिगमन की जांच के लिए हर दिन चलाते हैं।
हालांकि इस नियम का अपवाद है कि परीक्षण बाहरी परिस्थितियों पर निर्भर नहीं होने चाहिए, अधिकांश समय नियम का पालन किया जाना चाहिए, जिससे आपके परीक्षण सूट को नियतात्मक और विश्वसनीय होने का लाभ मिलता है।